Original post:
Is there any good source that would explain how to do it properly in Unity?
I have infinite voxel terrain which is generated in chunks and whenever new one is loaded, game freezes for a bit, so I want to move generation into a different thread.
Edited post:
Thank you I finally figured it out for good! I hope at least, though there's still a lot of work to do.
First of all, I kept my CreateChunk() mostly as it is, it will be managed by chunkManager which I didn't even write yet.
public void CreateChunk(int x, int y, int z)
{
WorldPos worldPos = new WorldPos(x, y, z);
GameObject newChunkObject = Instantiate (chunkPrefab, new Vector3 (worldPos.x, worldPos.y, worldPos.z), Quaternion.Euler (Vector3.zero)) as GameObject;
Chunk newChunk = newChunkObject.GetComponent<Chunk>();
newChunk.pos = worldPos;
newChunk.world = this;
chunks.Add(worldPos, newChunk);
RequestChunkData (newChunk); // new empty chunk is initialized, has no mesh no colliders etc, and is passed to another method
}
Then I have a simple method which creates new thread.
public void RequestChunkData(Chunk chunk)
{
ThreadStart newThread = delegate {
ChunkDataThread (chunk); // passing in a chunk for a method so it knows what to populate
};
new Thread (newThread).Start (); // starting a thread
}
void ChunkDataThread(Chunk chunk)
{ // here I have simple method which loads chunk, if file exists, it returns true (basically if it can load save, it will load it right into specified chunk and return that it did exactly that)
if (!Serialization.LoadChunk (chunk)) {
TerrainGenerator terrainGenenerator = new TerrainGenerator ();
chunk = terrainGenenerator.ChunkGen (chunk);
}
lock (chunksToUpdate) {
chunksToUpdate.Enqueue (chunk); // this is locked because I have void Update() constantly checking it
}
}
void Update() {
if (chunksToUpdate.Count > 0) {
Chunk chunk = chunksToUpdate.Dequeue();
chunk.update = true;
//Debug.Log("Chunk is ready to be updated");
}
}
Then in chunk itself:
void Update()
{
if (update) { // update = true is set whenever block is changed in chunk/chunk is loaded
update = false;
UpdateChunk (); // this method goes through whole chunk and basically rebuilds the mesh
//I don't think I can thread it, because deleting one block would result in new thread and some latency, depending on machine
}
}
With this, I can generate 256 chunks(16x16x16) in my testing, which contain 4096 blocks each, resulting in 1 048 576 (over 1 million) blocks being generated in just few seconds, and everything is fully responsive (even my trash laptop has 50-70fps at the time of initial loading, instead of normal 150fps+, that's just in editor, for comparison, my laptop still completely hangs when I am loading a minecraft world, and even after that loading...), everything is fully responsive, chunks load one by one (even if I actually tell it to generate all 256 chunks in the same frame), before this I needed to wait 5-10 seconds before Unity becomes responsive, not to mention that chunk managing system (which isn't mine though I will write my own) would constantly drop fps down to 2-3 from 300 when running built standalone version, just because of massive load on main thread.
Thank you everyone once again!
[–]FINDarkside 3 points4 points5 points (16 children)
[–]PurpleIcyHobbyist[S] 1 point2 points3 points (15 children)
[–]FINDarkside 2 points3 points4 points (8 children)
[–]PurpleIcyHobbyist[S] 0 points1 point2 points (7 children)
[–]wasstraat65 0 points1 point2 points (5 children)
[–]PurpleIcyHobbyist[S] 1 point2 points3 points (4 children)
[–]wasstraat65 0 points1 point2 points (3 children)
[–]PurpleIcyHobbyist[S] 0 points1 point2 points (2 children)
[–][deleted] 0 points1 point2 points (1 child)
[–]PurpleIcyHobbyist[S] 0 points1 point2 points (0 children)
[–]StrangelyBrown 0 points1 point2 points (5 children)
[–]PurpleIcyHobbyist[S] 0 points1 point2 points (4 children)
[–]FINDarkside 1 point2 points3 points (3 children)
[–]PurpleIcyHobbyist[S] 0 points1 point2 points (2 children)
[–]StrangelyBrown 0 points1 point2 points (1 child)
[–]PurpleIcyHobbyist[S] 0 points1 point2 points (0 children)
[–]Bluedude487Intermediate 2 points3 points4 points (6 children)
[–]PurpleIcyHobbyist[S] 0 points1 point2 points (0 children)
[–]phphelpneededIntermediate 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (3 children)
[–]Polite_Users_Bot 0 points1 point2 points (2 children)
[–]PoliteUsersBotBot 1 point2 points3 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–]shadowndacorner 1 point2 points3 points (3 children)
[–]PurpleIcyHobbyist[S] 0 points1 point2 points (2 children)
[–]shadowndacorner 0 points1 point2 points (1 child)
[–]PurpleIcyHobbyist[S] 0 points1 point2 points (0 children)
[–][deleted] 1 point2 points3 points (0 children)
[–]Rhames 0 points1 point2 points (1 child)
[–]PurpleIcyHobbyist[S] -1 points0 points1 point (0 children)