Stopping the rendering of an object nested in a prefab

I am attempting to write a 3d voxel engine from scratch. I am rendering cubes using 6 planes, in chunks of 16x16x128, like the well known game, Minecraft. However, this results in about 10250 batchs, 94779 saved by batching, but where I think is a huge source of performance drop, is the 43574 shadow casters. Now, my idea to solve this is to simply disable the ‘renderer’ component on every part of a cube that is invisible to the camera, on all the cubes. Now, obviously, I can’t use this:

void OnBecameInvisible(){
GetComponent().enabled = false;
}

void OnBecameVisible(){
GetComponent().enabled = true;
}

If I try that, then the renderer is disabled as soon as you can’t see a face on a cube, however, when you can see it again, because the renderer component is disabled, you don’t get the ‘OnBecameVisible’ event passed, and therefore it won’t re-enable the renderer.

I figured this could turn into a discussion, so I put it on the forum instead of Answers.

So my question then, how can I only draw objects that are visible to the camera on the screen.

Note: I can’t use occlusion culling because the prefabs of blocks are instantiated at runtime.

My guess is that when an object doesn’t have a renderer component, the engine sees no point in sending “onBecomeVisible” to it, because if it has no renderer, it is not visible.

Trying to implement cubes as actual objects (especially with separate object for cube parts) is a wrong idea.

Either build a polygonal mesh for the whole chunk of voxels:

Or you use techniques like raycasting.

With separate componens for every part of the cube, your game will suffer from heavy cpu overhead.

1 Like

@neginfinity That’s pretty much what I was thinking I’d have to do. I was avoiding this simply because ‘my way’ was simpler, but this was just the confirmation I needed that ‘my way’ wont work. Thanks!

I’m fairly sure this wouldn’t help you anyway. Unity isn’t dumb, if an object is definitely out of frame and OnBecomeInvisible is called, you can bet whatever you like that the Renderer is doing nothing. So turning off the Renderer won’t save you any rendering time.

Best thing to do is combine the cubes into a single mesh, as suggested.

@Kiwasi No, I have checked and when I go into the scene view and go under the map, it is definitely still rendering the faces that are invisible, this is also evident with the amount of triangles being renderer easily reaching 22 million.

To clarify, although the chunk is 16x16x128 I am not rendering every block there. I used to carve out caves, draw the blocks around the caves, then draw the blocks at the surface, and draw neighboring blocks when you removed a block, and stop drawing blocks below an added block.

Notice the use of used to. Now I am doing what was suggested and procedurally generating a mesh instead of cubes alll over the place. Working on getting my texture atlas to work right now, so it looks like this.

The little cylinder is what I am currently using to represent the player. This is only one chunk, and I have drastically increased chunk size to see how the terrain looks on a larger scale. Frame rate is much better compared to what I was doing a couple of days ago. Only ~131K tris being rendererd, Achieving 71.5FPS constantly. Previously I achieved 3 FPS.

Since I’ve got this far, does anyone have any advice on removing the triangles drawn on the side of the chunk? The tutorial I followed was cut short after generating one chunk, and I think I can fairly simply generate multiple chunks from here, however since this chunk with the outside faces alone has about 40k extra tris rendered, that would not scale up nicely. Also, the bottom is being rendered. further adding about 500 tris, however if I try rendering multiple chunks (and my goal is 12 chunks in each direction, at 16x16x16 size) that equates to ~13.5k extra tris per chunk, and in such a view distance would mean there are 2 million extra tris being rendered.

Help would be appreciated, haha.

Edit: Texture atlas wasn’t working because in the import settings of the atlas, it defaulted to automatically up the resolution to a power of two, when my original resolution was 768x768 thus screwing up my textures. Now to assign different textures on the atlas to different blocks instead of random vaues!

Edit 2: Terrain now loads dirt texture, working on different textures for different directions of objects on top for grass etc.

Yeah, but if its rendering the faces, it won’t be calling OnBecomeInvisible. OnBecomeInvisible doesn’t get called unless Unity is absolutely sure an object is hidden. Which normally only happens with frustum culling, occlusion culling and the like.

Its why OnBecomeInvisible is useless for something like detecting if a player can see an enemy in a FPS game. OnBecomeInvisible doesn’t indicate no pixels are present on the screen, it indicates Unity isn’t going to bother processing the renderer. Search the forums for “weeping angels” to find some more in depth discussions.

But anyway, I digress.

@Kiwasi Okay, thanks for the info.