Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Camera "Depth" order affects collider hit order, but is essential to determine render order

Discussion in 'Editor & General Support' started by chrisbrett665, Jun 1, 2022.

  1. chrisbrett665

    chrisbrett665

    Joined:
    Feb 8, 2018
    Posts:
    2
    I have a 2D game in Unity 2021.3. I have 3 cameras, all in the same position, each configured to render different layers via the "Culling Mask". The reason for this is so that I can apply different post process effects to different layers (e.g. no post-processing for text on UI, heavy bloom effect on one thing I want to really glow, light bloom effect on everything else).

    I have the cameras' "Depth" set so that it renders things in the right order.

    This looks great.

    However, after implementing that, I have found that it has broken my mouse click events. I have objects with a higher Z value (further away from camera) triggering their OnMouseDown handlers instead of objects with lower Z values.

    Experimenting to find out why, it turns out it's tied to the layers the objects are on, and which camera (and therefore render order) they are in.

    It doesn't seem like this should be the case, given that the design principle seems to be the opposite for sprites - render order can be specified, and z-position can be changed, allowing render order and click event order to be controlled independently. And it doesn't feel like cameras should affect collisions, aside from for mouse events providing the vector for a ray. Thoughts on that?

    I also couldn't find this behaviour documented, which lead to a lot of experimenting to find the cause. Hopefully this thread can help with that for others.

    Is there a way around this? Potentially switching from built-in render pipeline to URP? But it feels like I should stick with built-in given I'm a Unity rookie. Is there a better design pattern I should be following?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,951
    Whoa, 100% confirmed!!! Nutty. Never tried OMD with a multi-camera setup.

    And it is definitely NOT documented, at least not here:

    https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnMouseDown.html

    Of course a physics ray works as expected, since it knows nothing about camera.

    You could just do that... you could even have an interface that those OMD-ish objects express and use GetComponent<IMyInterface>() to see if it exists, and then call it, just as if it was OMD.

    eg, based off my test:

    Code (csharp):
    1. using UnityEngine;
    2.  
    3. // @kurtdekker - constantly raycasts into the scene to see what it hit.
    4.  
    5. public class RAY : MonoBehaviour
    6. {
    7.     string last = null;
    8.  
    9.     void Update ()
    10.     {
    11.         var ray = Camera.main.ScreenPointToRay( Input.mousePosition);
    12.  
    13.         string what = "nuthin";
    14.  
    15.         RaycastHit hit;
    16.         if (Physics.Raycast( ray, out hit))
    17.         {
    18.             what = hit.collider.name;
    19.         }
    20.  
    21.         if (last != what)
    22.         {
    23.             Debug.Log( "RAY: on " + what);
    24.         }
    25.  
    26.         last = what;
    27.     }
    28. }
     
    chrisbrett665 likes this.
  3. chrisbrett665

    chrisbrett665

    Joined:
    Feb 8, 2018
    Posts:
    2
    Thanks Kurt, makes sense.

    It's rather a shame that this needs a bunch of extra boilerplate to get working as intended... Feels like the framework should really handle this for us.

    For now I'm just going to work around it by re-arranging which objects are in which layers, which layers render in which camera, and which order the cameras render in - luckily for my use case I happen to be able to get away with that.
     
    Kurt-Dekker likes this.