Render EZ GUI Always on Top

I have a GUI built with EZ GUI. Unlike the built-in Unity GUI system, EZ GUI’s components exist in 3D space and can be overlapped by other game objects. The general solution is to place the GUI components very close to the camera.

However, in my case, I need a better solution. My camera will go through objects at certain times and this will cause game objects to overlap my GUI.

What can I do to have the EZ GUI always render on top of all other game objects?

You can render the GUI through another camera, and set that camera to render after your primary camera. Just make sure the GUI camera clear out depth buffer first.

This way there’s no chance you’ll get clipping with the rest of the world, since the depth buffer is reset and the GUI will be drawn last.

  1. To do this, make sure all your GUI stuff is on a GUI layer.
  2. Then add a Camera looking at the GUI objects.
  3. Set GUI camera Clear Flags to Depth Only.
  4. Set GUI camera Culling Mask to your GUI mask.
  5. Set GUI camera Depth to some value greater than your other camera (like 1000, whatever).
  6. You also should remove your GUI mask from your main cameras Culling Mask, otherwise it get rendered twice.

Reply to OP’s comment (Explaining depth buffer somewhat)

The depth buffer is used to determine the depth of an individual written pixel. Basically - when a pixel is to be rendered, it’s first tested to the depth buffer. If it’s closer to the camera than the previous existing pixel, then overwrite the existing pixel color & depth. Any pixels that are further away won’t get rendered. It’s basically what makes your GUI hide behind other objects. By using another camera that is drawing after the main camera, we can rest assured all other objects have used the depth buffer appropriately so we can then throw it away. It’s only there to determine which pixels should be rendered and to speed up rendering by avoiding rendering the same location several times. We clear the buffer because we don’t want our GUI to be hidden from other pixels that are already in the screen. And the way we do this is just by setting Clear Flags to Depth Only in the GUI Camera, as described above. You don’t need a much deeper understanding as Unity will take care of the buffers for you.

So basically, you’ll render all objects in the scene except GUI through the first camera. It will record pixel color in the color buffer and pixel depth in the depth buffer. Every pixel has to pass a test to check if it’s “in front” of any other pixel. If it is, overwrite it. Then once we’ve rendered all objects through the first camera, we start rendering through the second (GUI) camera. All the color and depth is still in the buffers, so anything the camera sees will be rendered on top of this first render pass. Since we want our GUI to become always on top, we can just clear out the depth buffer but keep the color buffer, so the depth information of the rendered scene is lost. This way we can’t fail a depth test to the rendered scene.

If you want to know more (random stuff): You can simplify thinking about the depth buffer as a screen where objects near you are black and objects far out are white. Like a black/white fog. Usually, solid objects have depth write enabled and transparent objects have depth write disabled. Ideally, solid objects are rendered front to back (to ensure the first objects cover the depth buffer with “near” pixels - avoid repainting the screen) and transparent objects are rendered back to front due to blending effects. Note that when you’re rendering normal transparent stuff (particles, whatever) you aren’t clearing the depth buffer. You just stop writing to the depth buffer. You only test against what’s there. We render transparents back-to-front because otherwise nearby objects get objects further back painted on top of them (since we can’t write to depth buffer). We can’t write to the depth buffer since transparent pixels should not block drawing. If we did, we couldn’t see other transparent objects through the gaps of transparent materials that were rendered afterward. Handling transparent geometry is cumbersome since you have to batch geometries for efficiency, but doing so you’ll end up with objects crossing each others depth. Hence we try to render them back-to-front with depth write off and depth test on.