Unity3D and C# - Coroutines vs threading

I’m developing a terrain generation system. The terrain is split up into smaller chunks which can be loaded and deloaded.

The problem is that the generation of the chunks can be a bit on the heavy side.

This can cause small noticeable lags as you walk around.

My first thought was to add threading support by doing all heavy calculations in a thread

(Since I know the Unity3D API is not thread-safe I kept all Unity related objects and calls out of the threading).

Problem is I can’t find any way to invoke the thread method back to the main thread of Unity.

My second option it seems is to look into coroutines. From what I understand coroutines allows you to break from a method and return at a later frame to finish it.

(But would coroutines actually be effective for my situation then? For example, if I split the generation method up into 4 frames, would users with fast computers will be punished if their CPU’s could have squeezed more per frame, or have I misunderstood something?)

I would love to hear your suggestions.

That’s quite simple :wink: You should use a class which represents a threading job. This class will be initialized by the Unity main thread. Then you start a worker thread on a function of that class and let it do it’s job.

Here’s the important part: Of course you store this job somewhere on the Unity side and have the Update loop (or a coroutine) continously checking an “isDone” variable in your class which will be set by the worker thread when it’s finished and when it stored all data it produced. It’s important that you make the access to this isDone boolean thread safe since both threads will need to access it.

edit

I just took a closer look at my first (untested) example. Unfortunately you can’t use lock on value types like a bool, so you need any kind of reference type as lock handle. I’ve made a small “framework” for a threaded job:

public class ThreadedJob
{
    private bool m_IsDone = false;
    private object m_Handle = new object();
    private System.Threading.Thread m_Thread = null;
    public bool IsDone
    {
        get
        {
            bool tmp;
            lock (m_Handle)
            {
                tmp = m_IsDone;
            }
            return tmp;
        }
        set
        {
            lock (m_Handle)
            {
                m_IsDone = value;
            }
        }
    }

    public virtual void Start()
    {
        m_Thread = new System.Threading.Thread(Run);
        m_Thread.Start();
    }
    public virtual void Abort()
    {
        m_Thread.Abort();
    }

    protected virtual void ThreadFunction() { }

    protected virtual void OnFinished() { }

    public virtual bool Update()
    {
        if (IsDone)
        {
            OnFinished();
            return true;
        }
        return false;
    }
    public IEnumerator WaitFor()
    {
        while(!Update())
        {
            yield return null;
        }
    }
    private void Run()
    {
        ThreadFunction();
        IsDone = true;
    }
}

This would serve as base class. Just create a concrete Job class which overrides the ThreadFunction function and implement your code. Here’s an example:

public class Job : ThreadedJob
{
    public Vector3[] InData;  // arbitary job data
    public Vector3[] OutData; // arbitary job data

    protected override void ThreadFunction()
    {
        // Do your threaded task. DON'T use the Unity API here
        for (int i = 0; i < 100000000; i++)
        {
            OutData[i % OutData.Length] += InData[(i+1) % InData.Length];
        }
    }
    protected override void OnFinished()
    {
        // This is executed by the Unity main thread when the job is finished
        for (int i = 0; i < InData.Length; i++)
        {
            Debug.Log("Results(" + i + "): " + InData*);*

}
}
}
This is how you would use the job class:
Job myJob;
void Start ()
{
myJob = new Job();
myJob.InData = new Vector3[10];
myJob.Start(); // Don’t touch any data in the job class after you called Start until IsDone is true.
}
void Update()
{
if (myJob != null)
{
if (myJob.Update())
{
// Alternative to the OnFinished callback
myJob = null;
}
}
}
edit
I just added the WaitFor coroutine which allows you to easily wait in a coroutine for the thread to finish. Just use
yield return StartCoroutine(myJob.WaitFor());
inside another coroutine. This can be used instead of calling Update manually each frame.

Coroutines aren’t really appropriate for this. Everything is still run in the main thread in that case, and there’s no effective way of distributing CPU usage, which is especially important considering that nearly everything these days has at least two CPU cores.

Can use a volatile IsDone rather than locking for efficiency.

Let me ad my two cents as well. I am also making Minecraft-inspired voxel game but with smooth terrain. After various bench, I ended up implementing my entire voxels stuff directly in C++ with PolyVox, as a DLL. This way, the generation is lighting fast. C++'s DLL uses worker threads, the Boss-and-Employees pattern styles. It exposes C functions so Unity can request loading/unloading of chunks, checking for results and fetching meshes.
A C# coroutine constantly polls the C++ library for “Job Results” each frame. If there is a mesh generated, this coroutine “imports” the mesh. The process is not so complicated, the threading model was more chalenging than sending of the meshes to Unity. I basically create byte array with vertex, index and splatting buffers, then in Unity generate the mesh and splatting maps.