I'm very new to the concept of multithreading, so I'm still learning and have no idea if what I'm doing could be considered heresy or not. I'm developing a game right now in my free time for fun in Unity, mainly as a way for me to learn more about 3d environments, and in it, I'm adding terrain generation. I tried to add multithreading but I don't think I did it correctly or in an efficient way as my game stutters a lot when loading chunks.
Here's how the multithreading looks in my terrain generation class:
public class TerrainGenerator : MonoBehaviour {
// Other global variables
public GameObject angularWPPref;
private List<AngularWP> renderList;
private List<AngularWP> awps;
private bool threadRunning = false;
private Thread myThread;
void Start() {
renderList = new List<AngularWP>();
awps = new List<AngularWP>();
for (int x = 0; x < wpAmount.x; x++) {
for (int z = 0; z < wpAmount.y; z++) {
GameObject worldPiece = Instantiate(angularWPPref); // Create the game object for the chunk/worldPiece
worldPiece.GetComponent<AngularWP>().setPosition(new Vector3(x * worldPieceSize.x * voxelScalar, 0, z * worldPieceSize.z * voxelScalar));
// Set the position of the worldPiece
awps.Add(worldPiece.GetComponent<AngularWP>());
// Add the Angular World Piece class object from the game object to a list so the chunk data can be added to it in the other thread.
}
}
}
void Update() {
if (awps.Count > 0 && !threadRunning) {
ThreadStart newThread = delegate {
generateVoxels(awps[0].position, awps[0]);
};
myThread = new Thread(newThread);
myThread.Start();
threadRunning = true;
}
// Start a new thread if there are more chunks to be loaded and myThread isn't running
if (renderList.Count > 0) {
renderList[0].setup(); // Initialize the mesh and add the material
renderList[0].refreshMesh(); // Clear the mesh
renderList[0].finalize(); // Add all vertices and tris to the mesh, recalculate normals, and add the mesh to the game object
renderList[0].initialPhysicsSetup(); // Set up the physics of the mesh
renderList[0].setPosition(new Vector3(renderList[0].position.x, 0, renderList[0].position.z)); // Set position again (because for some reason it was getting set in random places on the y-axis)
renderList.RemoveAt(0); // Remove the current world piece from the render list
}
}
public void generateVoxels(Vector3 position, AngularWP awp) {
awps.RemoveAt(0); // Remove the current world piece from the list
Thread.Sleep(1);
// Terrain Generation Code
awp.renderMesh(); // Create the mesh
renderList.Add(awp); // Add the world piece to the render list
threadRunning = false; // Tell the program that this thread is done running
}
}
Is there anything really noticeable that I've done wrong that I'm not seeing? The code works properly and generates the terrain correctly, so there aren't any errors, it's just that it stutters.
The only thing that I could see causing problems is the fact that I'm only using 1 additional thread to load the terrain as opposed to multiple, so maybe it's still slowing down because of that? That doesn't make a lot of sense based on my understanding of how multithreading works, but maybe I'm wrong.
Another point where it could be an issue is starting the thread or finishing rendering the current chunks when using the data in the main thread. I could see this causing problems, but I'm not sure how I would improve it.
I've taken a look at Unity's job system, but I couldn't figure out how to convert my code to work with it and felt like trying to learn how to multithread could be more beneficial since I could use the skills in other non-Unity projects in the future. Is this something that I should return to and give it another shot or can I achieve the same thing with multithreading?
I'm really lost when it comes to this stuff, so any suggestions are greatly appreciated.