1
\$\begingroup\$

What I am in need to achieve is to have a Sprite always facing the camera identically to what happens with any simple game UI object, but instead of always displayed above everything else, it should be always displayed behind everything else.

How can I achieve that in Unity using C#?

Regarding the always-behind rendering, I tried setting the Sprite's "Order in Layer" to 0 or to negative values, with no success. I also tried setting all game objects to a greater value than the sprite's:

    go.GetComponent<Renderer>().sortingLayerName = "Test";
    go.GetComponent<Renderer>().sortingOrder = 1;

That did not work as well.

What would be the correct way of making a sprite to be always displayed behind everything else (other sprites, GUI and 3D meshes) - preferably not having to resort to shaders, if possible?

PS:regarding the effect of the Sprite always facing the camera as in a game UI, I suppose it will be only a matter of updating its rotation towards the camera - but I would be happy to find out if other approaches are avialable/more suited to the task.

\$\endgroup\$
2
\$\begingroup\$

You can do this with two cameras with different culling masks.

When you have multiple cameras in your scene, each camera will be rendered separately. The culling mask decides what will be rendered by the camera. Then the output of all the cameras get drawn on top of each other in order of their "Depth" value.

  • Click on "Layers -> Edit Layers" and create a new user layer "Under".
  • Assign that layer to the game object of your sprite.
  • Make sure everything else has the "Default" layer assigned to it.
  • Create a second camera which is identical to the first. Make sure it also maintains the same position, rotation and other settings so both cameras always show the exact same view frustum (assuming you want the back-sprite to move just like everything else moves).
  • On the first camera (the "under"-camera) set:
    • Clear Flags: "Skybox" / "Solid color" (whatever you want to be the background)
    • Culling mask: "Under"
    • Depth: -1
  • On the second camera (the "everything else" camera) set:
    • Clear Flags: "Depth Only"
    • Culling mask: "Default"
    • Depth: 0
\$\endgroup\$
7
  • \$\begingroup\$ Thanks for your answer! I will try it in a few minutes. I have to tell you, though, that due to my former experience with multiple cameras, I am a bit concerned about the performance burden of having two cameras working (performance is currently critical, due to the other characteristics of the game and to the low-end platforms it is aimed at). Do you think that, if performance is a concern, then a shader solution would be more in order? \$\endgroup\$ – Kim Shutter Apr 24 '16 at 8:56
  • \$\begingroup\$ @KimShutter It shouldn't affect performance at all. Remember that each camera only renders what's on its culling mask. Each camera renders a different layer, so the number of rendered polygons stays exactly the same, just the order in which they are rendered changes. \$\endgroup\$ – Philipp Apr 24 '16 at 9:00
  • \$\begingroup\$ It makes sense, because in this particular case cameras won't be rendering the same objects and by your comment my guess is that the overhead of having multiple cameras is negligible. \$\endgroup\$ – Kim Shutter Apr 24 '16 at 9:16
  • \$\begingroup\$ The one performance hazard here is overdraw, if a lot of these sprites are ultimately covered and not visible. If you find that's a problem, and most kf your other content is opaque geometry, then a shader-based solution may help by allowing you to draw these sprites after all opaque geometry, and benefit from early Z testing discarding much of the work. \$\endgroup\$ – DMGregory Apr 24 '16 at 13:01
  • \$\begingroup\$ @DMGregory You were precisely correct. That is exactly what happened. In the beginning, I had tried the following: I created a points-mesh, and in its material's shader, each vertex creates a quad, textured with a sprite-texture from an atlas. I didn't work well due to overdraw. But after thinking a bit about your comment, I guess the reason here is because that big points-mesh would be never scaped in the Z-testing, right? So I should rather create individual meshes for each sprite and just assign them a simple shader that forces them to be draw behind everything else. Is that correct? \$\endgroup\$ – Kim Shutter May 15 '16 at 23:48
-3
\$\begingroup\$

Try drawing the sprite before anything else.

\$\endgroup\$
2
  • \$\begingroup\$ Thanks for your answer, but that seems to be precisely what I am asking about, just in a different manner. Would you care to elaborate on how can I do that in Unity? \$\endgroup\$ – Kim Shutter Apr 24 '16 at 8:05
  • \$\begingroup\$ Ehr. I don't know. That's basically the rule in every visually outputting program, I don't know if there's a specific way for Unity. \$\endgroup\$ – user6245072 Apr 24 '16 at 8:14

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.