Best Way to Instance Thousands of Grass on a Mesh?

Hey there!

My game infinitely generates tiles which the player travels along. I am struggling to solve this problem and would love ideas or a better approach.

I need a good solution for spawning grass and other vegetation which uses Shader Graph shaders for wind sway.

I have tried DrawMeshInstanced; the problem with this is that I don’t have a good way to control which Matrices to draw.

My current idea has been to associate grass matrices with the tile beforehand by raycasting and storing a List<Matrix4x4> on each tile. Then when the player enter’s the tile, they will instance every Matrix4x4 in the tile, as well as in the nearest adjacent tile.

This would work if I could figure out how to store the Matrices on each tile (Unity prefabs won’t do this by default).

Another problem with this approach is that the tiles can be very large and tank performance. Frustum and occlusion culling are basically out of the picture as far as I know because GPU culling is not supported with shader graphs, and the CPU frustum culling using culling groups and reconstructing the matrices is likely less efficient than just drawing all the matrices. Also, I would have to convert the matrices on each tile from local to world coordinates whenever they spawn in, and I’m not sure if that is efficient or even possible.

I have also tried creating a moving grid around the player that randomly spawns rows and columns of grass as the player travels, using a noise texture such that the randomness of the grass spawns is persistent, but the problem is the number of raycasts that have to be performed every frame.

Note: I have to raycast to place the grass because it uses the terrains vertex color as a spawn rule

Prefabs are terrible for performance too. And I honestly don’t want to store thousands of grass prefab transforms in my scene.

Here is a picture from my scene.

If I can avoid raycasting at runtime, I’d love to.

Does anyone know how its done in Rust, for instance?

I think the best option is to use Vegetation Studio Pro. with this you can have incredible numbers of vegetation (trees, grass, bushes), and it renders with good performance.

@ChiliStudio u can use the asset GPU instancer from the asset store or u can use object pooling which might give the same performance:- GitHub - keypax/object-pooling-in-unity-demo: This demo project shows custom implementation of Object Pooling used in our upcoming game: Pelagos: Rise of Greece

BatchRendererGroup

Update: The solution for me was to purchase GPU Instancer which uses indirect instancing, and supports HDRP shader graph shaders with one extra node they gave. GPU Instancer handles occlusion culling and frustum culling. I then store the grass/rocks/flowers position, rotations, and scales on a script on the tiles when I perform the raycasts (before runtime). Then when tiles spawn in, I take this data and form arrays of matrices that take the local position /rotations and convert them to the world, then tell the GPUInstancer to make instances at those matrices with the associated GPUI prefabs. --All along with a custom spawning script I made which uses vertex colors and noise textures for distribution. When the tile needs to delete, I just remove all the instances within the bounds of the tiles mesh! Works perfectly and I don’t give up any performance.