0
\$\begingroup\$

I am using cellular automata to randomly generate caves in Unity. Attached is a screenshot:

enter image description here

The black area represents walls. Walls can contain resources that can be mined.

Walls are made of blocks. A block should be destroyed when it is mined.

The naive approach would be to render a cube for each wall block. This won't work though because it will require too many objects to be on screen at once, even if the wall blocks are clipped to the viewport.

So how should I go about this? I was considering grouping sections of wall blocks together in a single mesh. When a block is destroyed, the mesh would be re-rendered with vertices for the block removed.

Or is there a better way?

\$\endgroup\$
  • \$\begingroup\$ As far as I know you've hit the nail on the head. Grouping cubes into bigger meshes in which you can merge triangles is the usual choice, and I don't know of any other. \$\endgroup\$ – Quentin Feb 15 '17 at 8:51
  • \$\begingroup\$ How many objects would be rendered in the worst case ? Can you lower that number? \$\endgroup\$ – jgallant Feb 15 '17 at 11:37
1
\$\begingroup\$

A group of cubes are often called chunks. A voxel engine is the name of engines that generate meshes for this type of data.

However, if your world is flat and your camera close you might be able to get away with approximately drawing what is on the screen. Use a pool of GameObjects to be used for drawing what's on the screen. Unload blocks or chunks when moving away and load blocks or chunks when you get near them.

\$\endgroup\$
  • \$\begingroup\$ Do you mean doing this by using FOV borders? It's kind of occlusion culling. I'm curious if there is a shader that can do this, because enabling-disabling might be not the best way, because you would anyway leave colliders to detect which objects to enable, so basically just turn off mesh render, though collision calculations are still there and mb shader work too. \$\endgroup\$ – Candid Moon _Max_ Feb 15 '17 at 17:01
  • \$\begingroup\$ No, you load and unload everything on the fly depending on the position of the camera. If you only ever need 1000 objects max you create a pool for 1000 objects. \$\endgroup\$ – Madmenyo Feb 15 '17 at 17:03
  • \$\begingroup\$ Yeah, but how do you detect objects that are in the range of camera? It's easy to say, but you would need some kind of jagged array that his indices correspond to position of the camera in the worlds space. Or collision detection of blocks. Or script that checks position of every block or even worse script for every block? You won't go every frame through all those 1000 objects checking if they are in range.That is why occlusion culling has kind of octree that checks neighbours in some range or something like that and perhaps has a collision detection for every camera in the scene. \$\endgroup\$ – Candid Moon _Max_ Feb 15 '17 at 17:12
  • \$\begingroup\$ Have chunks. Your camera center is only pointing at one chuck. If 9 chunks are enough you render the ones around it. \$\endgroup\$ – Madmenyo Feb 15 '17 at 17:16
  • \$\begingroup\$ Thanks! The camera will not be close. And the user will be able to click around on the map, so I won't be able to pre-render the cubes off screen. Can you suggest a voxel engine for Unity? \$\endgroup\$ – Simian Feb 16 '17 at 9:39
1
\$\begingroup\$

I would divide map onto different parts of some area. For example if you have 1000 units = 100 y units and 100 x units you divide generated area to 1000/100 = 10 parts that have area 100, 10 y, 10 x.

Before that you generate black part as a 1 mesh and then generate other things inside that mesh if you need it, but then I would suggest to cutout space for these objects as probably they will have some scripts attached to them and they can't be part of the mesh.

And then while you divide your mesh into chunks with 100 area you divide the mesh too, add to those chunks some script that it's x, y position in jagged array of all chunks. Raycast from camera to enable current chunk neighbour chunks((x;y) +(0;1), +(0;-1), +(-1, -1).....). And if the chunk you were raycasting changes find the difference in x, y in array. Then you have all you need to find chunks that need to be disabled in array.

As for the mesh. You can raycast it and rebuild mesh on point where it was raycasted, but that is complicated and somehow inefficient and for example if you want to have blocks that change texture or crack it would be pain to do that. So what I suggest is those blocks that are near white area should be just normal blocks not attached to the whole mesh. And also for optimization those blocks could consist of group of 4 blocks, so if one block from the group gets destructed, mesh that is near those group should rebuild and on it's place should appear new group of 4 blocks. So now if player made a tunnel between mesh, the whole mesh would not rebuild, but just a part that was divided and also if he decides to just dig 3 blocks and go on it's better when he doesn't rebuild the whole mesh.

Also I would just made it not a mesh, but just a bigger cube, that gets replaced with 4 smaller and so on.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.