Monday, August 16, 2010

Safe Multithreading in Unity3D.

Working with multiple threads is often a necessary evil.

This is how I do it safely inside a Unity3D component. There are only certain times when it is safe to read or change variables in other components. For example, you will encounter problems if you try and modify or query Physics components while a FixedUpdate is occuring! This component uses a Mutex to let the thread know when it is safe to use other game objects.

using System;
using System.Threading;
using UnityEngine;


public class ThreadedComponent : MonoBehaviour
{
Thread thread;
Mutex mainLoop;

void Awake() {
mainLoop = new Mutex(true);
thread = new Thread(ThreadWorker);
}

void Start() {
thread.Start();
}

void OnApplicationQuit() {
thread.Abort();
}

void ThreadWorker() {
//Catch and report any exceptions here,
//so that Unity doesn't crash!
try {
_ThreadWorker();
} catch(Exception e) {
if(!(e is ThreadAbortException))
Debug.LogError("Unexpected Death: " + e.ToString());
}
}

void Update() {
//Gives the thread a chance to work with gameobjects.
mainLoop.ReleaseMutex();
mainLoop.WaitOne();
}

void _ThreadWorker() {
while(true) {
//Play nice with other threads...
Thread.Sleep(0);

//Do random work here...

//Wait till it is safe to work with GameObjects.
mainLoop.WaitOne();
//Work with gameobject in here...
//But don't take too long!
mainLoop.ReleaseMutex();
//Signal Unity that we're done with GameObjects.
}
}
}

2 comments:

Waz said...

It seems Unity 3 breaks this, as just about anything you might do with a gameobject is prevented by Unity, giving a "can only be called from the main thread" error.

Ray said...

I found the same error message with Warwick

Popular Posts