Unity Pattern For Moving Some Objects Between Scenes? - unity3d

I'm looking for a pattern to transition between scenes, moving one instance of an object to the next scene and then later returning it to the prior scene, but without destroying the other objects that were in the prior scene. Here is the context:
When my game loads, it connects to my server to get the list of characters the player can control and instantiates them dynamically from a prefab.
The loading script moves each character game object to the main scene and then loads that scene.
The main scene now has the characters, which can be interacted with. So far, so good. One of the commands is to pick a specific character and send them on a task, which has its own task scene.
I can move that character to the task scene and move them back when the task is completed. However, the other characters who were not on the task and should not be in the task scene are now destroyed because the main scene was unloaded.
I'm looking for a pattern to accomplish this. Most of what I've read suggests using DontDestroyOnLoad, but this actually moves all characters into all scenes, which results in too many characters in the task scene. Another option might be to create a game object that holds all the character information, pass that between scenes and have logic in each scene to re-instantiate the appropriate character[s] in that scene. This feels like a lot of overhead since I have no other reason to be wiping and recreating them constantly. Perhaps a third option is to restructure my game so the task scene is just added to the main scene and shows up as some kind of overlay that blocks/captures input. This sounds messy and likely to have performance issues (targeting Android).
Does anyone have a good pattern for this?

with the scene manager you can create an empty scene, in this empty scene you put all of the objects you want to keep.
After you unload your first scene (not the one you create) and you load the next scene.
When your next scene is load you transfer all the object from the scene you create to the scene you just load.
PS : you have multiple scene load at the same time check this link for more informations :
https://docs.unity3d.com/ScriptReference/SceneManagement.SceneManager.html

Turning comments into an answer.
Static variables can be accessed from any scene. Depending on the number of each class type you need, you can either instantiate a static class, or a static List/Array of class. Once you add your objects to it, you can access them from anywhere.
As long as this doesn't become a memory concern (thousands of large objects, eg), this should work well for your purposes (a few characters that need to persist throughout the game anyway).

Related

How can I access an object's components from a different scene?

I have a Player gameObject that has a script on it which keeps some variables inside it. I created a scene which acts as a main menu and has "Shop" part in it, which has upgrades in it, basically I need to access Player gameObject's script from a different scene so I can modify variables from main menu scene. How can I do that ?
check this out:
https://docs.unity3d.com/ScriptReference/Object.DontDestroyOnLoad.html
once your player is loaded this will keep him in every scene until you choose to release hiim, meaning when you load your menu scene he will be there to access.
now since we know hes there, we can:
(note that player is your script with the variables not your actual player)
ScriptName player = GameObject.FindObjectWithTag("yourtag").GetComponent<ScriptName>();
Be default the components are instances of a class. If there isn't a GameObject with that component in the currently loaded scenes, there is nothing to access.
If I recall you can now load more than one scene at a time.
If there is a GameObject with that script currently loaded you can use:
https://docs.unity3d.com/ScriptReference/Object.FindObjectsOfType.html
or even better
use singleton design pattern, in case you have only 1 player at a time.
I guess you want to save these upgrades for the next run of the game, so you can use PlayerPrefs
https://docs.unity3d.com/ScriptReference/PlayerPrefs.html
If you want to save more than 50 values of data I would suggest using a file based DB like SQLite, it takes little time to setup and works very fast. And it is a lot more readable than using PlayerPrefs.
How about static class?
You can keep values there and access it from any place you want :D

Do Meshes get reloaded when switching scene?

Lets suppose I have a scene with several meshes like trees, boxes, etc. lets call it level 1.
After I finish playing level 1 I switch to level 2 like this.
SceneManager.LoadScene (1, LoadSceneMode.Single); //level2 scene index is 1
The thing is level 2 uses the same meshes level 1 uses. Do they get unloaded -> reloaded?
I'm not talking about DontDestroyOnLoad, as I dont need the same instances of the GameObjects in the level 2 scene.
I'm talking about the Model Data of each object (the meshes), not their instances. I know the instances are deleted, but I think Unity someway knows the next scene uses the same Meshes and keeps them. I just need to know if the Meshes are unloaded and reloaded when switching scene.
Objects that you don't call DontDestroyOnLoad on are destroyed once you change the scene using LoadScene (as if you called Destroy on them all), so yes the get reloaded. They are destroyed then (if they're present in the next scene) they're re-instantiated.
If you do edits to a specific object instantiated in a scene then these edits belong to this object.
If you load the same scene more than once then this specific object will have your edits. However if you load a different scene that has this prefab then the prefab will be a new one without the edits.
If you want all object instantiated to be like this object you have to edit the prefab. To do this you just click the "apply" button.
This will make all objects that become instantiated have the edits.
If you want some object to have the edits and some not to have them you make a separate prefab, just drag the "name" of this object from the hierarchy into your project folder. You've just created a new prefab and you can use it.
Also remember that this doesn't apply to edits done within the game. These are edits that you do (as a developer not as a gamer) in the scene view. Game view edits (for example if a player squishes a cube) are lost after game close.

Object resetting after loading a scene for the second time in Unity [duplicate]

This question already has answers here:
Unity game manager. Script works only one time
(5 answers)
Closed 6 years ago.
I have a game with three scenes, two level scenes and a menu scene. When I press play on my level scene the first time, everything works perfectly, but when I go to the menu scene and then later return to the level scene,
the references on the scripts attached to the NetworkManager GameObject were reset. On the scripts shown in the picture below, for example, all but the references that were linked to prefabs in my assets were reset.
I've tried assigning each and every variable with code instead of doing it manually, but even that doesn't work.
This GameObject does have dontdestroyonload on. Why are these references getting reset specifically on this object?
I don't have enough rep to comment, but did you save your scene after you added the references to the objects?
Answer (By Aaron Ge): I unchecked Don't Destroy On Load and Run In Background, and then my issue was fixed. I am unsure of how this fixed my issue, but it did.
Possible Explanation: http://answers.unity3d.com/questions/734445/scripts-in-other-scenes-still-executing.html
If you use DontDestroyOnLoad on objects that are placed in a scene, make sure that you either:
Load that scene only once. That's usually called a loading scene. The scene just contains certain manager objects and it immediately switches to the menu scene / whatever... You would never load that first scene again.
If you want to load the scene again and you used DontDestroyOnLoad on one or more object, you have to destroy the objects manually. You can't prevent the objects from being created again since they are part of the scene. Usually al objects get destroyed automatically when you load a new scene, DontDestroyOnLoad prevents that.
I unchecked Don't Destroy On Load and Run In Background, and then my issue was fixed. I am unsure of how this fixed my issue, but it did!

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.

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.