Working with the threading system in Unity

December 31, 2015

Unity seems to have a multi-threaded system, but I could find no way of accessing the dispatcher. Consequently, it’s necessary to create some kind of self-rolled task queue. The specific problem that I faced was with using the timer; here’s the code for the timer:



public class MasterScript : MonoBehaviour
{
    private Timer \_timer;

    void Start ()
    {
        \_timer = new Timer();
        \_timer.Interval = 1000;
        \_timer.Elapsed += \_timer\_Elapsed;
        \_timer.Start();
    }

    private void \_timer\_Elapsed(object sender, ElapsedEventArgs e)
    {
        SpawnNewObject();
    }
}

The idea being that every second, and new object would appear on the screen. However, as soon as you run this, it crashes (or as close as Unity comes to crashing):

FindGameObjectWithTag can only be called from the main thread

The solution that I came up with was as follows:



public class MasterScript : MonoBehaviour
{
    public static Queue<Action> TaskQueue;

    private void \_timer\_Elapsed(object sender, ElapsedEventArgs e)
    {
        SpawnNewObject();
    }

    private void SpawnNewObject()
    {
        TaskQueue.Enqueue(() =>
        {
            var newObj = Instantiate<GameObject>(MyObject);

Then, simply change the Update function to run them:



    void Update ()
    {
        if (TaskQueue.Count > 0)
        {
            TaskQueue.Dequeue().Invoke();
        }
    }

I’ve used the idea of a “Master Script” to deal with the queue, and this can be queued to from somewhere else in the game, which makes it more flexible.



Profile picture

A blog about one man's journey through code… and some pictures of the Peak District
Twitter

© Paul Michaels 2024