Geeks With Blogs
Jeff Krebsbach
My Unity project has a class (ClientSettings) where most of the game state & management properties are stored.  Among these are some utility functions that derive from MonoBehavior.  However, between every scene this object was getting recreated and I was losing all sorts of useful data.  I learned that with DontDestroyOnLoad, I can persist this entity between scenes.  Super.


The problem with adding DontDestroyOnLoad to my "ClientSettings" was suddenly my previous scene would stay alive, and continue to execute its update routines.  An important part of the documentation helps shed light to my issues:

"If the object is a component or game object then its entire transform hierarchy will not be destroyed either."

My ClientSettings script was attached to the main camera on my first scene.  Because of this, the Main Camera was part of the hierarchy of the component, and therefore was also not able to destroy when switching scenes.  Now the first scene's main camera Update routine continues to execute after the second scene is running - causing me to have some very nasty bugs.

Suddenly I wasn't sure how I should be creating a persistent entity - so I created a new sandbox project and tested different approaches until I found one that works:

In the main scene: Create an empty Game Object:  "GameManager" - and attach the ClientSettings script to this game object.  
Set any properties to the clientsettings script as appropriate.
Create a prefab, using the GameManager.

Remove the Game Object from the main scene.

In the Main Camera, I created a script:  Main Script.  This is my primary script for the main scene.

<code>
public GameObject[] prefabs;

private ClientSettings _clientSettings;

// Use this for initialization
void Start () {
GameObject res = (GameObject)Instantiate(prefabs[0]);

}
</code>

Now go back out to scene view, and add the new GameManager prefab to the prefabs collection of MainScript.

When the main scene loads, the GameManager is set up, but is not part of the main scene's hierarchy, so the two are no longer tied up together.

Now in our second scene, we have a script - SecondScript - and we can get a reference to the ClientSettings we created in the previous scene like so:

<code>
private ConnectionSettings _clientSettings;

// Use this for initialization
void Start () {
_clientSettings = FindObjectOfType<ConnectionSettings> ();

}
</code>

And the scenes can start and finish without creating strange long-running scene side effects.
Posted on Monday, August 11, 2014 9:56 AM unity , unity3d | Back to top


Comments on this post: Unity DontDestroyOnLoad causing scenes to stay open

# re: Unity DontDestroyOnLoad causing scenes to stay open
Requesting Gravatar...
Realizing that this is some months old,I'd like to say a few things just for those watching it.
First off,DontDestroyOnLoad is meant to be used in conjunction with additive load and Unity's streaming level API.So that you can have the persistent things in one scene file and then add and remove things on demand.
Instead of having a camera object in every level you could have the camera and script in the initial persistent scene and then just AdditiveLoad the second and third etc.As soon as SecondScript.Start is called you can find the reference to what you want.
Though a better solution would be to handle any kind of connection between ClientSettings/GameManager and scripts of other scenes that reference the ClientSettings in the GameManager script.Since it's the persistent one and the one in charge of using AdditiveLoad to load the other levels it would also fall to it to do the connections.
Using FindObjectOfType is wasteful in this respect.As well as Instantiate.Maybe in your situation its a waste you can afford but in most cases it's not the way to go.

In general,the Unity way isn't always the best way.A balance between regular .Net programming and Unity API is what you need.
Left by Nick on Mar 07, 2015 4:29 AM

Your comment:
 (will show your gravatar)


Copyright © jkrebsbach | Powered by: GeeksWithBlogs.net