- Home /
If I have an exiting player object setup how do I give the players selected character the game objects properties in the next level.
The title explains exactly what I mean. I setup a test level character for the gameplay and then made a character selection scene that brings the character selected to the gameplay scene. Showing code wont help in this case because I have a lot of scripts on the player object but I almost figured it out. How do I get that player selected from last scene to become the player object in the gameplay scene? I attached all my scripts to the new player character but one script is not working. I know this is vague I just want to hear thoughts...
Answer by Lysander · Jan 01, 2018 at 10:11 PM
In my opinion, every single scene should take static information, and use that to construct itself from scratch. Have a static character manager that tracks data used for characters, have a static achievement manager that holds achievement data, have a static quest manager that holds data for quests, etc...- none of this should be stored on GameObjects, because data is not a behaviour. Behaviours should USE this data by holding IDs and quick references to it, but shouldn't actually be the primary container for it (or the container at all, frankly).
Once you divide up the data from the behaviours, things become FAR simpler to manage when doing scene loads. The scene takes state data from the static managers, and then reconstructs itself to reflect that state appropriately. If a certain quest in the area is at X amount of progress, it knows to enable a triggerable object in area Y that triggers the next part of that quest when collided with. The character, as used in the last scene, can construct itself from a simple (universal) Character prefab, and just dump the data from the static manager into itself for the specific character its supposed to represent. For information that is NOT needed in the current scene, cached data like meshes and textures can be unloaded (AssetBundles are useful for this kind of thing) either immediately or if/when memory becomes an issue.
In short- don't treat GameObjects as if they're data. If data needs to be persistent between scenes, then a GameObject probably isn't the proper place to store it. If you like, you can use Singletons with DontDestroyOnLoad to mimic this kind of thing, but from a practical standpoint that only complicates issues- I only use singleton managers for behaviours (note: behaviours) that don't change from one scene to the next, not as data storage. This method also makes it trivial to generate save states and write them / load them from disk, because the GameObjects are only reflections of that data instead of actually holding it- the managers can all save and load ALL of the data they hold collectively, instead of needing to reach out and query dozens of scene objects or something.
This is only one way of managing things, and many would disagree with my choices here, so take this as just one option. Good Luck!
This is really well put. I would also add reading up on Scriptable Objects. I'm really just now getting to use them but they really help give me a more... maybe procedural(?) approach to managing data than using singleton based instances of managers as they are just empty game objects and probably less intuitive? I mean you don't store your working memories in a box in real life, you store them in a more abstract space in your $$anonymous$$d that you can best recollect yourself, if that makes sense.
I love ScriptableObjects and use them pretty extensively, but they can't be saved at runtime so they're mostly limited to data that doesn't change (static information storage). This can include the specific values used in algorithms for calculating character leveling (Character A increases dexterity 1.1 times faster than normal, vitality .8 times, etc), quest static information (not the player progress), achievement static information (again, not progress), and storing the references to assets in the project that can be loaded into your managers (meshes, textures, audioclips, etc), though I usually use AssetBundles for those so I can unload them when needed.
Data should really be well-divided between "static" and "instanced" to maximize performance, so "item data" that doesn't change from one instance of that item to the next is stored in ScriptableObjects (it never changes), but the data that's generated with RNG when the item is instantiated is stored in a runtime object. It's that runtime object that's serialized and saved to game save files- the static data is fine as it is. This can be applied to pretty much all types of save data, and massively reduces the amount that needs to be stored in game save files / checkpoints.