Hello, i am trying to implement a parent Singleton class, but when i try to assign instance to "this" its telling me that it cannot convert type Singleton<T> to T Here's the code: Code (CSharp): using UnityEngine; public class Singleton<T>:MonoBehaviour where T : MonoBehaviour { public static T s_instance { get; private set; } protected virtual void Awake() { if (!s_instance) { s_instance = this; DontDestroyOnLoad(this); } else { Destroy(gameObject); } } }
Your generic constraint is wrong. Your only condition is that T has to be any type derived from MonoBehaviour. It doesn't have to be derived from Singleton<T> at the moment. So in theory you could create a class like this Code (CSharp): public class TestBehaviour : MonoBehaviour { } And a singleton like this: Code (CSharp): public class SomeSingleton : Singleton<TestBehaviour> { } Of course the class in the type argument has absolutely nothing to do with the SomeSingleton class. Your constraint has to look like this: Code (CSharp): public class Singleton<T> : MonoBehaviour where T : Singleton<T> Even though it looks like a recursive definition (which it actually is), it will make it work. That's because whatever class you derive from your Singleton class must use itself in the T argument, no other class would match the constraint. Note that this kind of singleton (Awake initialized) is a quite specialized form. Initialization in Awake could cause race conditions if you try to use this singleton in other awake methods. Usually a FindObjectOfType approach is more flexible. In theory one could combine both approaches, but I like to have Awake available for the singleton itself. Finally in your implementation you silently destroy any duplicate instance. This is bad for debugging. You decided you want to have a gameobject based singleton. So there must always be just one instance. If there is another one, there's something fundamentally wrong. Instead of deleting the duplicate, throwing an exception or logging an error usually makes more sense since something in the setup is flawed and needs attention.
One small limitation with the lazy FindObjectOfType approach is that it can result in exceptions if the singleton is first accessed from a background thread, since FindObjectOfType is not a thread safe operation. In most cases this isn't an issue, but if you might potentially want to be able to use a singleton for example inside ISerializationCallbackReceiver methods, constructors or worker threads you yourself have started it's something to keep in mind.