Save/Load scene state for NPC actors - unity3d

All of the examples that I've seen of saving/loading a scene in Unity are either only saving/loading simple data (like the player's current health and position), or they're using a purchasable asset from the Unity store. The logic I need is a little more complex than having just a few predefined character parameters to save, and I'd rather learn the proper way to do this instead of buying a Unity store asset, so I'm asking here.
My scenes have some actors (NPCs and enemies) that are defined in the scene in the Unity editor, and some actors that are dynamically added via script during run-time. When the player saves, I want to record the current position/state/etc. of each actor, and then restore those actors to their last states when the player loads the game.
For the actors that defined in the Unity scene in the editor, I'll have to be able to look up the corresponding actor's data within my persisted data, and reapply that state to the actor. One of my main struggles here is being able to identify which set of data goes to which actor, since the actors in the Unity scene often just have generic names (like goblin) so there's no way to tell instance A from instance B. I thought about doing something like creating a PersistentData object that I can assign to each actor, and have the PersistentData object generate unique GUIDs for each actor. But for something as common as saving/loading scene state, I don't want to write a bunch of custom logic if there's already something built in that'll do what I want.
The second problem I'm having is that for actors that were dynamically added to the scene, I'll have to write some code to recreate them after loading the scene. Again, if there's already a built-in or accepted way of doing this, I don't want to write a bunch of code and reinvent a bad facsimile of an existing wheel.
My actors are all derived from MonoBehaviour, so I can't serialize them directly.
Is there an existing way within Unity to do this, or is there a commonly accepted way of handing this scenario?

Related

Automatically add platform area tile as player approaches the edge of current tile

Firstly, I'm new to Unity and I'm currently learning c#, please be gentle!
As a project, I'd like to create a simple 3d platform game. The idea being the player starts on a square tile, which is the game platform playing area. They explore different elements on this tile by moving around.
The perspective is 3rd person, so the player is looking down on the action. As they approach the edge of the tile Unity recognises this and adds another tile to the existing one, basically doubling the playing area.
As the player moves around further to the tiles edge, other tiles are added, increasing the discovered areas each time.
My thinking to achieve this would be to have 5 tile game objects, that have different elements like trees already built on them. The question is what is the best way to achieve this.
Would it be to build the complete level with all tiles and then using code restrict how far ahead the player can see, basically to the width and length of the tiles.
Or would it be better to trigger a new tile to appear as the player approaches the edge of the current tile.
Thought, links to example code that I could recycle would be very handy.
Thank you.
The question is primarily opinion based, but here is some advise:
There is no right way to make a game in unity. The correctness is mainly focused on performance; memory and processing.
There are two approaches here:
condition: Your world is endless (or very large) and player moves very slowly over time (say each tile takes more than a second to traverse).
solution: Do not instantiate everything at start, instead when player reaches the edge of a tile look for the next tile in your level structure to retrieve its data and then instantiate its objects.
condition: Your world is not very large (say it has less than overall 10K objects) OR player can move fast (as in Age of Empires game).
solution: Instantiate everything in loading phase and deactivate the game objects as they are being instantiated so that nothing is getting processed at the start of the game. In this case the level structure is a collection of game objects where you activate or deactivate them.
Hints:
Pooling is a good practice when it comes to repetitive objects. Pool is basically an empty game object with a script, and many many deactivated children.
e.g. If you have 1K trees of the same kind you better have a tree pool. Create a game object named tree pool, add a pool script to it and make that script generate 1K deactivated tree game objects in the loading phase. Then whenever your level generator needs a new tree just fetch a tree from tree pool and activate and reposition it. Make sure you clean up the pool after the game ends to prevent memory leak.
you can implement the pool as you like to provide object variations for a specific pool.
Instantiation in run-time is costly especially in mobile devices. Whenever you need to instantiate several game objects at once consider using a coroutine to prevent lag or freeze (this applies to loading phase too).
e.g.
IEnumerable CreateObjects(Data[] data)
{
foreach(var e in data)
{
Instantiate(e);//instantiate here and then wait
yield return null;//this line prevents lag
}
}
//...
StartCoroutine(CreateObjects(data));
//...
Having many active game objects is also costly especially in mobile devices. If many active game object have heavy scripts, the update methods will ruin performance. If many active game objects have rigidbodies or colliders the physics engine processing gets heavy.
Activating game objects is costly but less than instantiation, since it only runs Start method on its script if any, and also causes the physics engine to re-evaluate its structure if it has static collider or rigidbody.
Rendering is costly if only the rendered visuals are (fully or partially) visible to the cameras.
Create an editor project where you can design your levels. in this project you will make use of unity's editor classes to generate some kind of data (JsonObject) which represents your whole world. (collection of levels, tiles in each level and objects in each tile). Moreover you can have other data such as objectives and stuff each stored in a different JsonObject. Then use this data in your game by reading it and storing its structure in memory.
The reason I recommend JsonObject to store data is its size, portability, flexibility, accessibility and simplicity to work with. JsonObject is a dictionary stored as a plain text. and since it's a text you can encrypt it as you like

Having multiple unity scenes open simultaneously

I've been developing a board-style game in Unity3D. The main scene is the board, and has the data about each player and the current (randomly-generated) board stored within it.
I intend to add minigames into the game, for example when landing on a particular space on the board. Naturally, I would like to code the minigame in a separate scene. Is there a way I can do this without losing the instance of the current scene, so that the current scene's state is maintained?
Thanks in advance :)
Short answer: no, but there may be another way to do what you want.
A basic call to Application.LoadLevel call will destroy the current scene before loading the next one. This isn't what you want.
If your minigame is relatively simple, you could use Instantiate to bring in a prefab and spawn it far away from the rest of your scene. You can even use scripts to switch to another camera, toggle player controls and other interactions in the scene, and so on. Once the minigame is done, you can destroy or disable whatever you brought in, and re-enable whatever needs to be turned on in the main scene.
You could create a separate scene and call Application.LoadLevelAdditive to load that scene without destroying the current one. As above, you can then use scripts to manage which cameras and scene behaviors are active.
If you're careful, you don't really need two separate scenes. It may be enough to "fake" a scene switch.
Hard to give a complete answer without code, but you should look into the following things either with the unity documentation or youtube:
PlayerPrefs, this is one way of saving data, although i believe it isn't entirely secure i.e. being able to edit from a text file.
Serializable, this is apparently better than playerprefs.
DonDestroyOnLoad, can carry over information to multiple scenes.
Static variables, again not sure if this will help your particular problem.

Instantiate a prefab with a custom base object

Probably know the answer to this already but wanted to run this by the community anyways.
I have a custom object which contains the information I need to feed into a prefab.
I have read somewhere that messing around with contructors on prefabs is a bad idea. Is the best option then to simply pass the intitiatlization info via a method call on the prefab?
Ie: make a script for the prefab that accepts my custom object to configure it? Kind of a best practices question.
That's how I would do it. Basically the prefab needs a reference (not necessarily a separate script) to another prefab with the extra data needed.
Though the question is: why can't this data be in the prefab itself?
If the answer is "because the data is global and there are many prefabs" a good solution to that problem is ScriptableObject, which acts as a global data storage object. A scriptable object has a script and an inspector view like other game objects, and you can assign a reference to the scriptable object to prefabs which can then reference the global data.
Typically ScriptableObject are used for "raw data" or even as a lightweight game database.
Script that creates a ScriptableObject (there are many examples):
http://wiki.unity3d.com/index.php/CreateScriptableObjectAsset
This post explains the SO with a use case and code samples:
http://buchhofer.com/2010/10/unity-toying-with-scriptable-objects/

Understanding scenes in Unity3d

I have some confusion with scenes in Unity3d and I was not able to find any resources about them.
When should scenes be used? For example in a platformer would every level have to be a different scene? Would the main menu be a scene?
Can one overlay scenes?
How do assets work between scenes? Are they attached to each individual scene and have to be reloaded every time. Can one specify when an asset is no longer needed?
How does one send data between scenes/interface between scenes?
I understand that this is a broad topic, but I didn't want to spam with multiple questions.
When should scenes be used? For example in a platformer would every
level have to be a different scene? Would the main menu be a scene?
There are no general rules about that. In theory you may have just one scene for the whole game.
How you organize your scenes is entirely up to you and often depends on the type of game you are creating.
I think that there are at least 3 features to be considered of using scenes:
they are a logical container for all pre-instantiated objects that might be useful to divide your game into multiple levels/sections.
You can serialize cross references between GameObjects and Components inside a scene (if GO A needs a ref to GO B, and they belong to the same scene, the reference can be serialized and you no longer need to find the referenced object at runtime)
When you load (not in an additive way) another scene, the resources already loaded into memory are automatically released
Can one overlay scenes?
Yes you can using LoadAdditive. Unfortunately, once 2 scenes are both loaded into memory there is no automatic way of distinguish objects belonging to one or the other. So if you load additive a second level environment, it's up to you to keep track of the previous environment and explicitly destroy it if you need to.
How do assets work between scenes? Are they attached to each
individual scene and have to be reloaded every time. Can one specify
when an asset is no longer needed?
As defaults every GameObject of a scene will be destroyed once the new scene is loaded (unless you use an additive scene loading). A way to make a GameObject survive across scenes is to mark it using DontDestroyOnLoad.
If you need to share a particular "configuration" of a GameObject, you can store it as a prefab, and reference it across scenes (but remember that once in a scene it's a prefab instance, so the GO shares with the prefab the initial serialized and not overriden properties, but 2 instances of the same prefab are different objects).
How does one send data between scenes/interface between scenes?
Several ways, depending on what kind of persistent data you want to share.
For a particular GameObject instance let the object survive using DontDestroyOnLoad.
If you have some configuration data that doesn't need to be attached to a specific GameObject you can consider storing a ScriptableObject inside the AssetDatabase and reference it.
If you have data that must persist across different game sessions you can consider storing them into PlayerPrefs.
There are 2 other ways that I don't like, but just to cite them:
Using a static field can sometimes help you in doing that, but it has several problems from my point of view
Save and load from disk (could be useful in several situations, but often it's a platform dependent way and you can have some trouble especially on different mobile platforms)
This is a broad topic btw, I hope this answer can be a quite decent overview.
When should scenes be used? For example in a platformer would every level have to be a different scene? Would the main menu be a scene?
There is no rule as to how many scenes you need to have in your game. However, scenes allow you to logically separate out parts of your game from the rest of it. You have to have a minimum of one scene.
By main menu, if you are referring to a canvas with your UI elements, it will be IN a scene and not a scene itself. Canvas is just another GameObject, that we mostly happen to use for showing game menus. I mostly create a Canvas GameObject, put a script by the name of "UIManager" and put DontDestroyOnLoad on it, so I have access to it in all scenes. Make it Singleton and I ensure that it is not duplicated.
Can one overlay scenes?
Yes, there is no restriction as to how many scenes you can load at a time. What purpose do you plan to overlay scenes though? Maybe there is a better way than loading additively.
How do assets work between scenes? Are they attached to each individual scene and have to be reloaded every time. Can one specify when an asset is no longer needed?
Assets are what you see in your 'project' hierarchy. I think you meant "GameObject"s in the scene, and if so, think of your gameobjects as entities with components (Entity-Component System). All entities in a scene get destroyed when its parent scene is destroyed until explicitly stated not to, using DontDestroyOnLoad in some component (a monobehavior in case of unity). The destroyed ones will get garbage collected.
So how they are loaded (or reloaded) depends on your implementation, on whether you are instantiating/destroying them time an again or if you put their instantiated prefabs in a cached object and retrieving later from it.
How does one send data between scenes/interface between scenes?
Heisen covered the ones I could think of. Just to add a little bit to it, it also depends on how you want to the architect your project. So if you had an underlying data structure to e.g. hold Commands, you are free to use it in any part of your project
Most games would be organised to have scenes for every level(including the main menu) but that is entirely up to you.
You can use the data from one scene to another if you save it in a text file or binary. There are a lot of tutorials on how to do this. I find documentation helps a lot.
Assets are universal in a project.
You can not overlay scenes.
When should scenes be used? For example in a platformer would every level have to be a different scene? Would the main menu be a scene?
When to use a scene is up to you. If you are just starting I would recommend using a different scene for each section of your game.
Can one overlay scenes?
Yes, using LoadSceneMode.Additive(). (LoadAdditive() is obsolete)
How do assets work between scenes? Are they attached to each individual scene and have to be reloaded every time. Can one specify when an asset is no longer needed?
By default, assets are deleted when using SceneManager.LoadScene(). However, if you use DontDestroyOnLoad(), the object will not be destroyed when entering new scenes. If you want to only keep an object through a few scenes instead of all, use Destroy() with some boolean logic.
How does one send data between scenes/interface between scenes? I understand that this is a broad topic, but I didn't want to spam with multiple questions.
You can send data through scenes by using the aforementioned DontDestroyOnLoad(), referencing the data on different scripts, using ScriptableObjects, using JSON Serialization, using StreamWriter(), using PlayerPrefs (Don't use for important information), the list goes on. I would personally recommend using ScriptableObjects for their accessibility, and StreamWriter() for it's encryption capabilities.

RPG Game loop and class structure (cocos2D for iPhone)

I'm looking to make an RPG with Cocos2D on the iPhone. I've done a fair bit of research, and I really like the model Cocos2D uses for scenes. I can instantiate a scene, set up my characters etc. and it all works really nicely... what I have problems with is structuring a game loop and separating the code from the scenes.
For example, where do I put my code that will maintain the state of the game across multiple scenes? and do I put the code for events that get fired in a scene in that scene's class? or do I have some other class that separates the init code from the logic?
Also, I've read a lot of tutorials that mention changing scenes, but I've read none that talk about updating a scene - taking input from the user and updating the display based on that. Does that happen in the scene object, or in a separate display engine type class.
Thanks in advance!
It sounds like you might do well to read up on the Model-View-Controller pattern. You don't have to adhere slavishly to it (for example, in some contexts it makes sense to allow some overlap between Model and View), but having a good understanding of it will help you to build any program that has lots of graphical objects and logic controlling them, and the need to broadcast state or persist it to disc (game save), etc.
You also have to realize that cocos2d provides a good system for structuring the graphical scene graph and rendering it efficiently, but it doesn't provide a complete infrastructure for programming games. In that sense it's more of a graphics engine than a game engine. If you try to fit your game's architecture into the structure of cocos2d, you might not end up with the most maintainable result. Instead, you should treat cocos2d as what it is: a great tool to take care of your display and animation needs.
You should definitely have an object other than the scenes that maintain the game state, because otherwise where will all the state go when you switch between scenes? And within scenes/levels, you should simply try to use good Object Oriented design to have state distributed over objects of various classes. Each character object remembers its own state etc. Here you can see where MVC becomes useful: when you save the game to disc, you want to remember each character's health level, but probably not which exact frame index the sprite animation was showing. So you need to distinguish between the sprite and the character (model) itself. That said, as I mentioned before, for game objects that don't have a lot of logic attached to them, or which don't need to be saved, it might be ok to just fuse the Model and View together into one class (basically by subclassing CCSprite).
To pull off MVC the way it's supposed to be, you should also learn the basics of Key-Value Observing. (And you'd do well to use this replacement for Apple's interface.) In more intensely real-time games, techniques like this might be too slow, but since you're making a RPG (good choice for starting out) you could probably sacrifice performance for a more maintainable architecture.
The game scene (which is just another cocos2d sprite) plays the role of Controller, in terms of the MVC pattern. It doesn't draw anything itself, but tells everything else to draw itself based on inputs and state. It's tempting to put all kinds of logic and functionality into the game scene, but when you notice that it swells, you should ask yourself how you could separate that functionality into other classes. Analyze which type of functionality you're implementing. Is it to do with data and state (Model)? Or is it about animation and rendering (View)? Or is it about connecting logic with rendering (in which case you should try to make the View observe the Model directly)?
The game scene/Controller is basically a dispatch center, which takes input events (from the user or from sprites reporting that they've hit something, for example) and decides what to do with them: it might tell one or several of the Model objects to update themselves in some way, or it might just trigger an animation in some other sprites, for example.
In a real-time game, you'd have a "tick" or "step" method in the scene which tells all objects to update themselves. This method (the game loop) is the heart of the program and is run every time a new frame is drawn. (In modern game engines there's a lot of multi-threading but let's not think about that.) But in your case, you might want to create a module that can "play the game" completely separate from the game scene. Imagine creating a program that can play chess through the terminal, using only text input. If you create the whole game system in that manner, and then connect it to the graphics engine through a small and clean interface, you'll have a really maintainable app with lots of reusable code for future projects!
Some good rules of thumb: the model (data) shouldn't know anything about sprites or display states; the view (sprites) shouldn't contain any of the game's actual logic (the game rules) but only know how to do simple things like moving and bouncing and reporting to the scene if something complicated happens. Whenever possible, the view should react to changes in the model directly, without the controller having to interfere.