Reputation: 457
I'm a beginner to Unity.
I'm currently implementing Singleton.
I have questions while studying.
What is the best way to implement Singleton in Unity like the title?
I understand why use a singleton. that is.. " To create an object once and use it whenever need it. "
Do I understand it properly?
There are many ways to implement singletons. It's right? Then, Which part of the many methods are used in common?
My singleton code is:
public class GameSingleton<T> : MonoBehaviour where T : MonoBehaviour
{
protected static T instance = null;
protected virtual void Awake()
{
Debug.Log ("instance was !!!!! >>" + instance);
if(instance != null) // 최초 instance 유효성 검사
{
Debug.Log(">> Game Singleton already exist!");
return;
}
instance = FindObjectOfType<T>(); //
Debug.Log("FindObj" + "/" + "instance is >> " + instance);
}
// Use this for initialization
protected virtual void Start()
{
}
// Update is called once per frame
protected virtual void Update()
{
}
protected virtual void OnDestroy()
{
if (instance != null)
{
instance = null;
}
}
public static T Instance
{
get
{
if(instance == null)
{
GameObject go = new GameObject();
go.transform.position = Vector3.zero; // Vector3(0,0,0)
go.transform.rotation = Quaternion.identity; // 회전 없음
go.transform.localScale = Vector3.one;
go.hideFlags = HideFlags.HideAndDontSave;
instance = go.AddComponent<T>();
instance.name = (typeof(T)).ToString();
Debug.Log(">> Game Singleton instance create : " + instance);
}
return instance;
}
}
}
We'd appreciate it if you could review the code, but we'd also appreciate a few key points.
I have seen several documents, but they only get complicated. My level is very low. I would appreciate it if you could explain it easily.
Upvotes: 0
Views: 5643
Reputation: 946
There are plenty of Singleton pattern implementation available, but the Unity environment is completely different from other environments, so the implementation is completely different from others.
So in unity you should do some more things, for example you should make a preload scene for your singleton objects and place them as components in scene.
But you can learn the basics and fundamentals from Game Programming Patterns - Singleton and Wikipedia - Singleton Pattern
Here is some implementations of Singleton pattern in Unity:
Unity Official Wiki - Singleton
And the best implementation is Unity Community - Singleton
Upvotes: 2
Reputation: 1323
Here's some remarks about your code:
Inside getter of the Instance
property you have a line of code:
instance = go.AddComponent<T>();
The point about this line is that AddComponent<>
will cause creation of the script's instance and then calling Awake()
method. So you will create an instance of your sript by this line and it doesn't matter what's written in the Awake()
method. So you can get rid of Awake()
as it does nothing. The only case it will do some helpful work is when you'll try to create the first instance of your script (it'll just set the value of instance to the 1st instance). In other cases it's useless. So if you will create your singleton only by using Instance
property - you do not need that awake.
Awake
itself is a "kinda constructor" for MonoBehaviour scripts, but it performs differently. The point is that in pure c# you can easily implement singleton with the help of static constructor but you can't do it this way in MonoBehaviour. That means if you already have an instance of your singleton and you'll try to create your singleton instance with the line T myNewInstance = new T();
the second instance will be actually created. So your code won't protect you from direct creating of the instance.
Also, if you'll use gameObject.AddComponent<T>()
method, your singletone code won't prevent Unity from creating new script instance.
So, there's no 100% method to create a MonoBehaviour singletone in Unity, but there are some possible workarounds.
For example, take a look here. This solution has much similar to yours but it also uses public T GetOrAddComponent<T> (this Component child) where T: Component
helper extension method, which you can borrow to your solution.
Another possible solution is that you can create a non-MonoBehaviour derived c# singleton class like a wrapper for getting a MonoBehaviour class, which you want to have only a single instance. But you'll have to use only this wrapper to manage this MonoBehaviour class, otherwise you will be able to create as much instances of the MonoBehaviour as you wish.
Upvotes: 2