Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a Singleton in Unity3D

I'm currently attempting to use a Singleton as a global data structure for Task organization in a game I'm making in Unity.

My Singleton class code is as follows:

public class TaskManager : MonoBehaviour 
{
    private List<Task> Tasks;

    private static TaskManager instance;
    private TaskManager() 
    {
        Tasks = new List<Task>();
    }

    public static TaskManager Instance
    {
        get
        {
            if(instance == null)
            {
                instance = new TaskManager();
            }
            return instance;
        }
    }
}

I used this example as a basis for my class: https://msdn.microsoft.com/en-us/library/ff650316.aspx

However, the problem is, when I try to access the TaskManager in different scripts, the values don't get saved.

For example, in one script I do:

TaskManager tm = TaskManager.Instance;

Task newTask = new Task();
tm.PushTask(newTask);

print(tm.GetTaskList().Count);

Through this I can see that the TaskManager has a count of 1, showing the new task.

But then my other script attempts to read from the TaskManager:

TaskManager tm = TaskManager.Instance;
List<Task> l = tm.GetTaskList();
print(l.Count);

When I do this, the Count is returned as 0, showing that the above task from the world has not been saved to the TaskManager.

I'm pretty sure the error is resulting from me misunderstanding how to use Singletons. Do I need to implement a set property for TaskManager Instance? Or is there another mistake I'm making?

Thanks!

Edit:

The PushTask() code is as follows:

public void PushTask(Task t)
{
    Tasks.Add(t);
}
like image 794
Jestus Avatar asked Nov 01 '25 13:11

Jestus


1 Answers

Personally, I don't think that solution that you chose is a perfect one. For some time, I tried using "abstract" classes that didn't inherit from MonoBehaviours, to decouple logic from Unity mechanics — but found that this makes code bloated and unnecessary complicated. In fact, every class that doesn't only contain data but has some logic of its own ends up being a MonoBehaviour sooner or later, in my experience.

So, instead of removing inheritance from MonoBehaviour, I'd solve it by implementing the usual MonoBehaviour singleton pattern:

using UnityEngine;

public abstract class Singleton<T> : MonoBehaviour where T : Singleton<T>
{
    public static T Instance { get; private set; }

    protected virtual void Awake()
    {
        if (Instance == null)
        {
            Instance = (T) this;
        }
        else
        {
            Debug.LogError("Got a second instance of the class " + this.GetType());
        }
    }
}

And then just inheriting your class from it.

like image 105
Max Yankov Avatar answered Nov 03 '25 03:11

Max Yankov