0
\$\begingroup\$

I have been working on a simple chunk based terrain generation system, with voxel octrees. The overall method works pretty well, but testing this system with large amounts of chunks completely freezes the game/main thread until the generation process is finished. Looking for a solution, I read about threads and coroutines and I implemented a simple thread class (based on this template) to call the "generate" function from it. The only advantage I had was a faster generation, with full CPU usage, but the game still freezes until the chunks are completely loaded. Am I doing something wrong? Here some parts of the code:

public class ChunkThread : ThreadedJob {
  public Chunk chunk;
  protected override void ThreadFunction(){
    chunk.root = chunk.root.BuildOctree (chunk.pos, Chunk.size, -1);
  }
  protected override void OnFinished(){
    chunk.RenderChunk ();
  }
}

This is the simple Thread class I use to call the Build function, and the Render function when finished. This piece of code below is the start\update method for every Chunk gameObject (I kept only the relevant part), that simply creates the Thread instance and calls Start() pressing the mouse button.

void Start () {
  t = new ChunkThread ();
  t.chunk = this;
}
void Update () {
  if (Input.GetButtonDown ("Fire1")) {
  t.Start ();
}

Now, coming to the questions, what should I do to generate the terrain while still being able to play? Is there something wrong in my thread? Should I use a thread pool, if so how?

\$\endgroup\$
  • \$\begingroup\$ Whats this ThreadedJob class ? Not part of unity as far as I am aware .. you'll need to write some sort of threading code to pass the work off to another thread. \$\endgroup\$ – War Mar 14 '15 at 13:17
  • \$\begingroup\$ nvm ... just noticed the link to the code for it ... I took a similar approach to this. \$\endgroup\$ – War Mar 14 '15 at 13:23
0
\$\begingroup\$

I took a similar approach here:

https://github.com/TehWardy/ccoder-Voxels/tree/master/Assets/Tasks

My code basically does what the .Net 4 tasks stuff does (well some of it) in that I pass a lambda in and get a task back ....

var task = Task.Factory.StartNew(() => { return GenerateLotsOfData(); });

I then use update to handle when the task is complete ...

void update() {
  if(task.Complete) { var data = task.Result; }
}

Using my code I don't appear to get any locking problems.

The key difference I can see is that I limit the number of threads my tasking system can use, other than that it's pretty much the same approach.

\$\endgroup\$
  • \$\begingroup\$ We gave a shot at your solution and it works! We had too many threads and they were choking the CPU, your Factory was really helpful to understand the problem and how to solve it. Unfortunately the whole terrain contruction isn't really fast (we suspect our BuildOctree method isn't well optimized), can you please check our ThreadManager implementation and tell me if there are some logic errors? Thanks. \$\endgroup\$ – Andrea Mar 15 '15 at 12:27
  • \$\begingroup\$ looks pretty good ... I would create all the threads up front though, saves on a per frame check for number of threads and thread creation has an overhead ... its faster to check if a thread is busy than it is to create one. I used 2 lists, one for busy threads and one for free threads, and thread code always did some basic stuff like check if there's another item in the queue and kick one off when it's complete with a queued item. It saves you having to have something else handle that ... if work is waiting let the thread go pick it up. \$\endgroup\$ – War Mar 15 '15 at 21:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.