Need help understanding Application.LoadLevel() and DontDestroyOnLoad

Hello,

I am having some trouble with Application.LoadLevel() and DontDestroyOnLoad and was hoping someone could clear up the confusion. I have dont some looking around but it seems like what im seeing just doesnt seem right.

Right now, if I do not include DontDestroyOnLoad and reload the level via Applicaiton.LoadLevel, i get errors saying the game object doesnt exist anymore and it doesnt work. Its confusing because the game is actually running, but maybe there are things pointing to the old memory address, which doesnt exist anymore.

If I do include DontDestroyOnLoad and reload the level via Application.LoadLevel, objects end up getting recreated and I have no clue why.

From what I’ve seen, people use Singletons to get around this, but it just seems strange that for such a basic feature, I never see things like tutorials speaking about it. Am I to understand its better to allow something like a GameManager or GameController (call it what you will) to have a DontDestroyOnLoad and then allow that instantiate the objects at runtime? It just seems almost counter intuitive in some cases where you want to manually place something in your scene if it will always run into this issue.

From the sound of it, it seems like I just simply dont understand how these things work. I would really appreciate anyone being able to clear this up for me.

Thank you in advance

How are they being created in the first place? Is there some code that’s responsible for spawning your singleton objects?

As I often ask people working through this sort of problem:

  • When should this code run?
  • How many times should this code run?
  • How do you enforce that?

For example, if you’re spawning singletons in Awake(), you’ll need something that checks if you’ve already spawned this or that singleton before you go and spawn a second one.

This is one area where separation of concerns can shine. Should your PlayerController class know about the DataManager class? No! It should query the class, which should return data. If the DataManager internally spawns and caches a singleton while looking up data, that’s not the PlayerController’s concern.

At the moment, I dont have any singletons in place. I have a scene where the character is placed, along with the scene, assets, etc. I assumed that when you called Application.LoadLevel, that was pretty much like a reset function where the old objects aredestroyed and new ones are created.

However, it seems like I should use a singleton be used to instantiate objects then that class would a reset function so it can be moved back to the beginning of the level? Is that correct?

More or less, yeah. Every GameObject is destroyed, with the exception of the ones you’ve asked to keep.

Note, however, that Unity doesn’t do anything about duplicate objects in this scenario. If you mark the player with DontDestroyOnLoad, and the scene you’re loading also contains an instance of the player object, you’ll end up with two players.

That’s easy enough to check for:

public class Foo : MonoBehaviour {
	static Foo instance;

	void Awake() {
		if (instance == null) {
			instance = this;
		} else {
			Debug.Log("Destroying duplicate", this);
			Destroy(gameObject);
		}
	}
}

That would make sure that there’s only one Foo at a time, no matter how many Foos end up in the active scene.

If there’s any object you keep while reloading the current scene, you’ll need to handle the fact that you now have two of them.

Sometimes, you can just ignore it, though you should be careful about that – if your code assumes there will only ever be one of these things, and there are now two of them, that can cause trouble.

Sometimes, you can delete the original, though that may beg the question of why you bothered keeping it in the first place.

Sometimes, you can delete the “new” one from the reload, though you may need to “reset” the original to some state.

The third option seems the closest to a traditional singleton pattern (load once, keep forever), but all three of those are potentially useful depending on what exactly you’re trying to do.

I’m having trouble with this as well. I’m trying to keep GameController persistent between level loads. When the character reaches the end of the level, the score is incremented by one, and the level is reloaded. I see the score updated, then the level is reloaded and the score is reset to 0.

using UnityEngine;
using System.Collections;


public class GameController : MonoBehaviour
{
    public GUIText scoreText;
    private int score = 0;
    static GameController instance;

    void Awake() {
        if (instance == null) {
            instance = this;
        } else {
            Debug.Log("Destroying duplicate", this);
            Destroy(gameObject);
        }
    }


    void Start ()
    {

        UpdateScore();
    }
 
 
 
    public void AddScore (int newScoreValue)
    {
        score += newScoreValue;
        UpdateScore ();
    }
 
    void UpdateScore ()
    {
        scoreText.text = "Score: " + score;
    }
}