My scene consists of 524288 cubes, drawn as a landscape. The user should be able to traverse the landscape, freely. Right now, I’m drawing all of them, and my system slows to a crawl. Surprise!
Obviously, I don’t need to draw all the cubes. At any one time, they’re obscured by other cubes, not in the viewport, beyond the horizon, or too small to be worth drawing.
How do I deal with this in Unity, if I’m creating the objects with a script (specifically C#)?
Got ya. But these instructions (e.g. “baking”) appear to be related to static objects in the scene. All my objects are generated by a script, and their size changes during program execution.
How do I apply those concepts to my scripted objects? (The objects are all instantiations of a prefab.)
I suggest developing a chunking system. It’s basically necessary with voxel terrains until we have quantum computers.
Having your interaction / physics code run against >500,000 objects could be what is slowing it down. You can have a script that checks the distance between you and other things in the scene in a round robin style so you check maybe 50,000 per second total instead of 500,000 every frame. When certain voxels are within a certain distance, enable their interactability. When they aren’t, disable all the expensive things you don’t need. Once you have that in place, you can also easily implement your own LOD system if you don’t have unity pro
You said you’re working with cubes right now so maybe level of detail isn’t too much of an optimization. If you have high quality textures on the cubes, you can use LOD to make them really low quality ones when no one is close enough to see them.
The best way to have lots of objects is to not have lots of objects. Voxel systems construct meshes that contain a bunch of cubes each, instead of having an absurd number of actual cubes. You can’t use occlusion culling with this (not the built-in system anyway), since the meshes are constructed dynamically.
Thanks for your thoughts! All I have on the cubes (which are actually a set of quads I assembled in the editor) is a gradient done in shaders (not with textures). So…I guess I could turn off the gradients on objects not being seen?
No, Unity already uses mipmaps for textures, no need to do anything about that yourself (it would just slow things down). The point is to not use half a million cubes.
There’s no upper limit as far as I know; computer specs are all that matters. However brute-forcing 400K objects is still a pretty bad idea even if you get OK performance on your rig, because you could get much better performance by using fewer objects.
Not as one mesh (you can’t use more than 65K vertices in a single mesh anyway), but several. You change the appropriate vertices in a mesh when you want to update cubes. This would be useful. Also this.
Chunking only applies to situations where you’re not going to see it all at once. I’m not sure what you’re trying to do now with that screenshot. Are all of the cubes visible at once, or will the player’s view be somewhere in the middle? Implementing a chunk system, you’d divide that whole area into sections, as Eric suggested, and load&unload sections based on where the player is and what chunks the player can actually see. Minecraft implements fog so things fade after a certain view distance, and just beyond that view distance there is nothing. As you approach the fog, new sections of the world will be loaded in while sections you are moving away from will be disappearing behind you.
You’d still need to use chunking because you can’t have >65K vertices in a mesh. Also it would probably be useful to have smaller meshes (say 8-16K vertices) since updating vertices requires uploading them all, even if you’re just changing a few, so updating an 8K mesh is faster than updating a 65K mesh. It depends on how many cubes you’re updating at any one time.