I have a situation where two transparent meshes are close to each other, and nearly parallel. The problem I’m facing is that depending on where the camera is, Unity will render one of the objects in front of the other, which causes the meshes to “pop” behind or in front of each other.
For example, here there’s a wide blue mesh in front of a relatively smaller square piece of dark glass. From this position, the blue mesh is in “front” of the glass:
(I’ve set the alpha on the glass to 1 for this example, just to make it really obvious when the glass is in front of or behind the blue mesh.)
My assumption is that Unity chooses which order to render the objects based on the camera’s distance from the bounding box center. As I move the camera around, it’s closer to one of the centers than the other, so that one gets rendered first.
I was wondering what the options were for avoiding this kind of behavior?
I thought maybe “Sorting Priority” would help. But if I use that, the behavior is worse, and one of the meshes always appears in front of the other, even when it’s far behind the other.
Is there a trick to dealing with this? Is there even a name for this kind of issue?
Yes. It’s called “you’re fu…” uh…“you’re going to have to fudge some stuff.”
Your assumption about how Unity sorts things is correct. For general 3D objects are sorted by their bounds center distance from the camera.
The way I handle issues like this in the BIRP is with a Sorting Group and setting the sorting order via a custom script. This makes their render order explicit between the two objects, but still allows them to sort with other objects in the scene (now using the combined bounds center). It’s a hacky work around, but solves most of these kinds of issues for me. Unfortunately I don’t know if this works for the URP or HDRP, both of which have the Sorting Priority setting, though I believe it does.
This doesn’t help if you need the order to change based on the camera’s position, like if you’re viewing it from one side of the “blue mesh” or the other and you want the order to change. In that case I would probably use two one sided planes for either the blue mesh or the “glass” mesh and give them a unique sorting order. Or you could have the script that’s setting the sorting order change the order based on which side of a plane the camera is on.
But basically no general purpose transparency sorting algorithm can handle this situation perfectly, so you have to rely on a custom setup.
Or bite the bullet and make one of these surfaces use dithered transparency so it is actually opaque.
There is one “trick”.
If you are moving the camera conventionally, by changing it’s position, you will get positional variance: variable calculation error, that changes depth fighting like this whenever surface planes are very close.
If you maintain the camera at the origin, and move the model around the camera instead, that variance is removed and it may be enough improvement to produce consistent depth ordering.
Uh … yeah, no. You very clearly didn’t actually understand the problem here. This isn’t z-fighting, neither plane is writing to the depth buffer.
I appreciate the value of camera centric rendering systems for better precision, but not every problem is magically solved by it. You have a habit of popping into threads and recommending this as the solution without actually reading the problem to understand if it’s applicable or not.
edit: as an extra bonus point against your recommendation, I believe @dgoyette is using the HDRP here, so they are already getting the benefits of camera centric rendering as that’s how the HDRP works.
Thanks for the reassurance that I wasn’t just missing some simple thing. Fortunately, I have very few cases where this is an issue. In fact, it might only be the one I’ve posted here (it’s the only time I’ve noticed this happening.) So, I’ll do a one-off hack to the sorting order just for these instances, and see if that covers it.
This also marks the first time I’ve seen someone use the term “BIRP” for the built-in renderer. That gave me a chuckle.
As you’re in a simple case with two planes, couldn’t you setup a script that checks for the plane orientations and set their rendering order manually ? I’m thinking of doing the same in my game.