Approach for rendering 3D tiled based world?

Hey!

I have been trying to solve this problem for a while, but I can’t.
I have two data classes that represent the world. One is the Grid class, which has a multidimensional array, and the other the Tile class, that represents the tile (with information about it).

The thing is, for each tile I’m creating a GameObject that represents it (kinda like minecraft, for each position in the world it has a cube), but, the moment the world starts to have multiple gameobjects it lags or wont even load.

A world of 500x500 meters isnt that big to play on, but its 250k of gameobjects, so I’m guessing that I’m not approaching it right.

How should I do it?

You will need bite a problem from various points.

  1. Simplest is, reduce number of tiles.
  2. Use culling and pooling of tails.
  3. Bake terrain to single mesh.
  4. Use mesh optimization, I.e. LOD and like marching cubes.
  5. Use Draw Mesh Instancing API, to render things differently.
  6. USE DOTS (perhaps the hardest).

Some of them may be easier than other.
And that are only some of things, which you can do to optimise.

  1. Yeah, I guess thats an option, but games like Minecraft, or Dinkum are made with tiles, and are pretty big. I know minecraft uses your point 5. Don’t know about the other.

  2. I need to look into that, but it won’t even load when hitting play so the problem I guess it’s another.

  3. The gameobjects are literally planes haha

  4. Same

  5. Hmm, I have look about it a bit, but haven’t got nothing yet. I guess that I need to look more tutorials

  6. Yeah haha, maybe a bit harder, and I dont think that its the approach (But maybe an option)

You may need start the research here:
https://0fps.net/2012/06/30/meshing-in-a-minecraft-game/

Another idea that could work and is easier to use: A particle system.
Use the SetParticles method which is fast enough to not stutter with thousands of particles. However use a separate thread to prepare the data in the background and only add the tiles surrounding the player. That’s how minecraft does it too after all - you have a limited render distance. Re-trigger like every 16 meters.
Ideally you can have a handful of particle systems so you do not have to update everything every time.

Also a cheap way to save a lot of rendering: Do not add tiles that are completely burried.

Minecraft creates meshes representing the cubes and then renders that. Optionally with VBOs (Vertex Buffer Objects) for increased performance. We have a fairly in-depth thread on the topic that was active for 8 years.

https://discussions.unity.com/t/425242

2 Likes

Do not use 1 GameObject per metre cube, you have to really optimise mesh rendering - you generate an optimised mesh for say every16x16 group of cubes, hidden faces are not part of the mesh. But there have been many discussions on the techniques used as above

1 Like

Either use DrawMeshInstanced, or merge tiles together into larger meshes.

Those games do not create a gameobject per cube.

I guess that the limitation with creating your own mesh is that making a “complex” mesh (more than a cube at least) would be difficult.

Another option is checking this: Unity - Scripting API: Graphics.DrawMeshInstanced

Got a lot of good ideas from there!