简体   繁体   中英

How can I make my instance of a Singleton MonoBehaviour class start as new when reloading the scene?

I have a 'SingletonManager' class with an instance of the 'LevelManager' singleton (and interface to it). The 'LevelManager' GameObject is not supposed to be persistant throughout the application lifetime and should be replaced with a new instance every time a new level is loaded.

While running my current code, when the scene is loaded for the second time, 'LevelManager' seems to be missing, despite the GameObject (with script attached) being in the scene. I realise that this is probably because I am still trying to access the old reference.

What is the best way to ensure that my 'SingletonManager' holds the new instance of 'LevelManager' every time a new level is loaded?

My code (with irrelevance removed):

SingletonManager:

public class SingletonManager
{
    private static LevelManager instance;
    public static ILevelManager Instance
    {
        get
        {
            if (this.levelManager == null)
            {
                this.levelManager = GameObject.FindObjectOfType(typeof(LevelManager)) as LevelManager;
            }
            return this.levelManager;
        }
    }
}

Singleton, is not persistant:

public class Singleton<Instance> : MonoBehaviour where Instance : Singleton<Instance> {
    public static Instance instance;
    public bool isPersistant;

    public virtual void Awake() {
        if(isPersistant) {
            if(!instance) {
                instance = this as Instance;
            }
            else {
                DestroyObject(gameObject);
            }
            DontDestroyOnLoad(gameObject);
        }
        else {
            instance = this as Instance;
        }
    }
}

What i understand from your question is you need a new object as game stage is change ,
If i understand correctly then this may helps you.
Try Multiton pattern for your solution.
here is an example

class levelManager {
    private static readonly Dictionary<object, levelManager> _instances = new Dictionary<object, levelManager>();

    private levelManager() {
    }

    public static levelManager GetInstance(object key) { // unique key for your stage
        lock (_instances) {   
            levelManager instance;
            if (!_instances.TryGetValue(key, out instance)) {
                instance = new levelManager();
                _instances.Add(key, instance);
            }
            return instance;
        }
    }
}

Note:- I just give you an example not perfect code for your class
Reference link : http://en.wikipedia.org/wiki/Multiton_pattern

Simple solution:

Create a manager for the level managers. It should be persistant, and have an array of LevelManager prefabs (I assume you're instantiating them from a prefab?). When each level is loaded, have it spawn the appropriate LevelManager prefab (or build it or whatever is needed to create it).

Each level manager should simply set the instance in Awake, and let the level destroy it at the end. (ie. your non-persistant singleton.)

public class LevelManagerSpawner
{
    public GameObject[] LevelManagerPrefabs;

    void OnLevelWasLoaded( int levelNumber )
    {
        Instantiate( LevelManagerPrefabs[ levelNumber ] );
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM