Saturday, January 14, 2017

c# - In Unity, how do I correctly implement the singleton pattern?


I have seen several videos and tutorials for creating singleton objects in Unity, mainly for a GameManager, that appear to use different approaches to instantiating and validating a singleton.


Is there a correct, or rather, preferred approach to this?



The two main examples I have encountered are:


First


public class GameManager
{
private static GameManager _instance;

public static GameManager Instance
{
get
{

if(_instance == null)
{
_instance = GameObject.FindObjectOfType();
}

return _instance;
}
}

void Awake()

{
DontDestroyOnLoad(gameObject);
}
}

Second


public class GameManager
{
private static GameManager _instance;


public static GameManager Instance
{
get
{
if(_instance == null)
{
instance = new GameObject("Game Manager");
instance.AddComponent();
}


return _instance;
}
}

void Awake()
{
_instance = this;
}
}


The main difference I can see between the two is:


The first approach will attempt to navigate the game object stack to find an instance of the GameManager which even though this only happens (or should only happen) once seems like it could be very unoptimised as scenes grow in size during development.


Also, the first approach marks the object to not be deleted when the application changes scene, which ensures that the object is persisted between scenes. The second approach doesn't appear to adhere to this.


The second approach seems odd as in the case where the instance is null in the getter, it will create a new GameObject and assign a GameManger component to it. However, this cannot run without first having this GameManager component already attached to an object in the scene, so this is causing me some confusion.


Are there any other approaches that would be recommended, or a hybrid of the two above? There are plenty of videos and tutorials regarding singletons but they all differ so much it is hard to drawn any comparisons between the two and thus, a conclusion as to which one is the best/preferred approach.



Answer



It depends, but usually I use a third method. The problem with the methods that you used is that in the event that the object is included to begin with, it will not remove them from the tree, and they can still be created by instantiating too many calls, which could make things really confusing.


public class SomeClass : MonoBehaviour {
private static SomeClass _instance;


public static SomeClass Instance { get { return _instance; } }


private void Awake()
{
if (_instance != null && _instance != this)
{
Destroy(this.gameObject);
} else {
_instance = this;

}
}
}

The problem with both of your implementations is that they do not destroy an object that is created later. It could work, but one could throw a monkey wrench into the works that could result in a very difficult to debug error down the line. Make sure to check in Awake if there is an instance already, and if so, destroying the new instance.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...