- Home /
How to handle a MASSIVE amount of game objects?
My team and I are new to Unity, and have been struggling for the last several weeks with one of three problems: either high memory usage or low frame rate or frame rate spikes. We are developing a 2D game (using 3d physics because we are using character controller) that uses procedurally generated maps similar to Terraria and Starbound.
Our smallest map is 4096 blocks wide by 1024 blocks high. For a total of 4,194,304 blocks. Each block game object contains a: SpriteRenderer, box collider, BlockObj script and BlockData script.
Unity will not allow us to create this many blocks on even a small map, much less a large without exploding, so we have implemented chunks to help alleviate the issue. Chunks allow us to set the biome for that chunk, and each chunk will be X blocks wide and X blocks high. Each contain contains a block array, and a box collider (for player entered chunk triggering).
We only load the blocks contained in chunks which either: contain the player, or border a player containing chunk. We implemented a coroutine on block loading to reduce the spikes, but then our frame rate drops while the chunk blocks are loading.
We also have a garbage method which takes chunks that were loaded, and no longer border a player containing chunk and is not a player containing chunk itself. Blocks in the garbage list get destroyed in a coroutine over time.
We poll a special class every 1 second to update player containing chunks, player bordering chunks, and garbage chunks. The system is optimized to not reinstantiate or create duplicates.
With the current system we have excellent memory usage, typcially below 150 MB for a small map. But depending on what settings we tweak whether it be the rate at which we update garbage, player chunks, player bordering chunks (every second), or the rate at which blocks are created/destroyed within their coroutines (0.1f), it just doesn't matter. We either have unacceptable frame rate spikes or frame rate drops over time.
We have tried several other methods in the past as well such as creating faces and turning the blocks into a chunk mesh. This resulted in crazy high memory usage (900+ MB for a small map) but had excellently stable frame rate. We also looked into batching for our current setup and were disappointed to see that the batching is only useful for meshes (which we are obviously no longer using).
I am beginning to think maybe we are doing something wrong. We are new to Unity after all. We need to manage between 4,194,304 and 16,777,216 blocks at a time, in addition to other game objects such as player, flora & fauna, background tiles (for creating that lovely wooden background wall in your house i.e.), environment backgrounds (majestic mountain views!), enemies, NPCs, projectiles, dropped objects, chests, etc. What would be the best way to accomplish this?
Have you considered using Unity's Terrain? You can modify its height and textures during runtime. Unity's terrain is probably more optimized than whatever mesh-combining systems you had. This way the amount of GOs you need to handle would be cut drastically.
Destroying GameObjects is somewhat heavy on processing. Try to ins$$anonymous$$d use SetActive. Whenever the player gets too far from the object, disable it so that Unity ignores it. Then re-enable it as the player nears it. Also, if you have pro, Unity's occlusion culling might help as well.
Answer by scipiothegreat · Mar 07, 2014 at 11:06 PM
The way most people make voxel games is having each chunk be only one gameobject. The chunk contains (or retrieves) voxel information, then uses that to create a mesh at runtime. So instead of having, say, 16*16 gameobjects per chunk, there is only one gameobject that represents a 16*16 area with a single mesh. This saves a lot when it comes to memory and especially drawcalls. A chunk with one mesh should run much faster and use less memory than a chunk and 256 gameobjects.
For the collision, I'm not sure if you could use a mesh collider. I think it would still be possible to use several box colliders that are turned off when you don't need them.
Also, instead of destroying chunks when they're not in use, you should consider having an object pool and returning the chunk to the pool.
Answer by guinoalaskapp · Aug 30, 2021 at 04:21 PM
Yea, but, what if i need to use SpriteRenderers, and some C# lógic for each tile?
And, I use diferent gameObjects cuz of a paralax efect per tile
Your answer
Follow this Question
Related Questions
How to form copies of yourself that follow you when you walk? (2D Platformer) 2 Answers
How to have graphic continuity in my chuncks ?(2d procedural / sprites) 1 Answer
The name 'Joystick' does not denote a valid type ('not found') 2 Answers
Why doesn't OnTriggerEnter2D get called? 1 Answer
Images won't import as sprites? 1 Answer