#Procedural Terrain Generation and object spawning

1 messages · Page 1 of 1 (latest)

crystal grail
#

Hello everyone,
I'm working on a procedural infinite terrain generation, and I've run into a significant performance issues regarding the instantiation of foliage, specifically trees (rocks etc.). I'm looking for advice on the most optimised and scalable approach to handle this.
Current Situation:
My world is procedurally generated and divided into chunks. As the player moves, new chunks are generated around them, and distant ones are unloaded. The terrain mesh is generated on the fly.
After a chunk's terrain is created, I have the data (positions, rotations, scales) for every tree that should exist within that chunk. The number of trees can be quite large, sometimes up to 5000 objects in the loaded area around the player.
The key challenge is that these trees are not just decorative. They are resources that the player can interact with (e.g., chop down for wood). This means each tree needs:
A Collider for physics interaction.
A script attached (e.g., TreeResource.cs) to manage its health, what it drops, etc.
The Problem:
My initial, naive approach of calling Instantiate() for every tree causes massive lag spikes and is completely unworkable. Even if I were to use a simple object pool, managing and activating/deactivating tens of thousands of GameObjects seems like it would still be a huge performance bottleneck, both for the CPU and memory. Besides that, there are 30+ different types of trees.
I understand that for purely visual objects, GPU Instancing (Graphics.DrawMeshInstanced) is the way to go, as it avoids creating GameObjects and significantly reduces draw calls. However, this method doesn't support Colliders or scripts.
TLDR;
What is the most efficient and scalable architecture to handle "spawning" a massive number of interactable objects on an infinite procedural terrain?
Any general direction/optimisation ideas are more than welcome 😄

turbid beacon
#

Well, if you're object pooling then spawning shouldnt be a problem, but if you're talking about how to you keep gameobjects/colliders to a minimum on a large level then you should segment out your level into sectors. If your character is in sector [1, 1], well we should populate this sector and all the neighboring sectors like [1, 0] with trees

#

Probably the most simplest way about it

jolly kestrel
crystal grail
# turbid beacon Well, if you're object pooling then spawning shouldnt be a problem, but if you'r...

Hey thanks for the reply, if by sectors you mean chunks, I have that implemented but still, spawning objects in neighboring chunks causes lag spike. I am still not sure if pooling is the right way to go here, because there are plenty of tree/rock variations and some area can have up to 500 of same interactable trees/rocks. By my calculation, lets say I have 30 unique rocks/trees and inside of pool I need to have around 500 for each of them, that's 15k objects. Not sure if that's the right approach. I've only worked with object pooling for one-same prefab.
I am now thinking out laud, but can I reduce lag by having ~5k objects in pool and change its mesh/material and attach scripts at runtime for each different tree/rock (when needed)?

turbid beacon
#

Are you using all 15k objects? You can probably generalize a lot of your pooling prefab such that all you have to do is attach some SO data to it to give it identity

#

And as far as the data struct for the pool, you can do something like a circular buffer if you don't want to dynamically shrink it

#

And yeah the SO can include material/mesh info

#

so what you ultimately are dealing with is what's loaded in the shader

crystal grail
crystal grail
crystal grail
turbid beacon
#

Pooling is more of a GC optimization

#

materials and meshes should be batched anyway

#

only time you need to create a new material is say if you do interact with a tree and want to chop away pieces

#

so technically you'll always be using these shared meshes and materials pooled or not

#

so even if you do pool by SOs, say you do have 1000 different SOs all loaded with material references using 8k textures, well that's a lot that's being loaded even if those gameobjects aren't being rendered currently.

#

I would expect Unity would probably help reduce what's loaded if it notices renders not using those materials, but not something I've looked into