In my 2D platformer I have a Dialogue Manager object and a Canvas to display the dialogue. I want to persist them from scene to scene. In order to do this I created a parent object with this script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Singleton : MonoBehaviour
{
private static Singleton instance;
public static Singleton Instance { get { return instance; } }
void Awake()
{
if (instance == null)
instance = this;
else if (instance != this)
Destroy(gameObject.GetComponent(instance.GetType()));
DontDestroyOnLoad(gameObject);
}
}
It does persist, but when I switch scenes I have two instances in my hierarchy. I have this Parent Object (With the dialogue manager and canvas) in every scene. But I want the original one to persist and the other one to be destroyed on entering the room. I need to have them in every room because of saving and loading.
I hope someone can help me understand what I should do differently to solve this.
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T instance = null;
private static readonly Object syncRoot = new Object();
public static T Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
{
instance = GameObject.FindObjectOfType(typeof(T)) as T;
if (instance == null)
Debug.LogError("SingletoneBase<T>: Could not found GameObject of type " + typeof(T).Name);
}
}
}
return instance;
}
}
}
For singleton-ish stuff I would highly recommend NEVER placing something in scene. That always just leads to sorrow and mass future disasters and confusions.
@Terraya 's solution above is definitely really nice and simple, but I like to take it one step simpler and do away with the inheritance because I believe it provides no value in this context and only confuses what is actually happening.
This is always my go-to solution:
Simple Singleton (UnitySingleton):
Some super-simple Singleton examples to take and modify:
Simple Unity3D Singleton (no predefined data):
Unity3D Singleton with a Prefab (or a ScriptableObject) used for predefined data:
These are pure-code solutions, do not put anything into any scene, just access it via .Instance!
If it is a GameManager, when the game is over, make a function in that singleton that Destroys itself so the next time you access it you get a fresh one, something like:
public void DestroyThyself()
{
Destroy(gameObject);
Instance = null; // because destroy doesn't happen until end of frame
}
There are also lots of Youtube tutorials on the concepts involved in making a suitable GameManager, which obviously depends a lot on what your game might need.