Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

UI toolkit system blocks Physics.Raycast

Discussion in 'UI Toolkit' started by RobbertGroenendijk, Mar 26, 2022.

  1. RobbertGroenendijk

    RobbertGroenendijk

    Joined:
    Sep 12, 2018
    Posts:
    10
    I tried the new UI toolkit today to make some UI buttons that overlay my gameview. I noticed that the UIDocument gameobject/component block all of the Physics.raycasts. Is there any way to circumvent this? Preferably per UI element. That way I can retain the game as it is now, and only block the raycast when the user actually clicks the button. As of now, no matter where the button is in the screen. All casts are blocked.

    I tried to set the picking-mode to ignore but this does not seem to work in my case (and figure it is also not meant to do this). Additionally, I put my UI on a UI layer and exclude that in my raycast as a layer mask, but this still does not work. Hopefully someone can point me in the right direction. Thanks in advance.

    - Unity 2021.2.17f1
    - UI toolkit / Unity UI 1.0.0
    - Input system 1.3.0
    - Setup for Android build target
     
  2. RobbertGroenendijk

    RobbertGroenendijk

    Joined:
    Sep 12, 2018
    Posts:
    10
    -SOLVED-

    I missed an event system in my scene, overlooked that bit.
     
  3. felipemullen

    felipemullen

    Joined:
    Mar 4, 2017
    Posts:
    44
    I am having the exact opposite problem:

    All pointer events are hitting the game world when I want it to only interact with the UI.
    I am on 2022.1.0b12. Is this configurable somewhere? The layer masks don't seem to affect UI Document components
     
  4. patrickjarnfelt

    patrickjarnfelt

    Joined:
    Jun 24, 2013
    Posts:
    28
    I am also having the inverse problem of the UI Document NOT blocking raycasts in the world, even though I want it to. My hacky solution would be to track if there are menus/modals open with saving it to a singleton and then disable all world interaction.

    Are there any options to have the UI toolkit block the raycasts only where there are visual elements visible?
     
  5. patrickjarnfelt

    patrickjarnfelt

    Joined:
    Jun 24, 2013
    Posts:
    28
    My solution was to have an invisible BG Visual Element that has PickingMode Position. Then everything above it that shouldn't block clicks get PickingMode Ignore (really, EVERYTHING otherwise it doesn't work). Everything that should block clicks above this element also gets PickingMode Position.
    This way we can infer that if the BG element got a click (actully PointerOverEvent), that means that nothing else of importance got a click. That means that we can "allow" raycasts in the world.

    I have a static variable where I save IsTouchAvailable.

    It is available if the BG got a PointerOverEvent and not available if the BG got a PointerLeaveEvent. These 2 events sandwich PointerDown and PointerUp, so you can reliably use those events elsewhere and just test the static variable IsTouchAvailable

    Code (CSharp):
    1.  
    2. public class TouchEnabler : MonoBehaviour
    3. {
    4.     public static bool IsTouchAvailable= false;
    5.     VisualElement _bg;
    6.  
    7.    void Awake()
    8.    {
    9.       var doc = GetComponent<UIDocument>();
    10.       _bg = doc.rootVisualElement.Q<VisualElement>("bg");
    11.    }
    12.  
    13.    void OnEnable()
    14.    {
    15.       _bg.RegisterCallback<PointerOverEvent>(HandlePointerOverBg);
    16.       _bg.RegisterCallback<PointerLeaveEvent>(HandlePointerLeaveBg);
    17.    }
    18.  
    19.    void OnDisable()
    20.    {
    21.       _bg.UnregisterCallback<PointerOverEvent>(HandlePointerOverBg);
    22.       _bg.UnregisterCallback<PointerLeaveEvent>(HandlePointerLeaveBg);
    23.    }
    24.  
    25.    void HandlePointerOverBg(PointerOverEvent e)
    26.    {
    27.       IsTouchAvailable = true;
    28.    }
    29.  
    30.    void HandlePointerLeaveBg(PointerLeaveEvent e)
    31.    {
    32.       IsTouchAvailable = false;
    33.    }
    34. }
    35.  
    Attach to the GameObject with the UI Document that contains the bg element that is at the lowest possible sort order
     
    horatiu665 likes this.
  6. horatiu665

    horatiu665

    Joined:
    Nov 22, 2012
    Posts:
    24
    I just wanted to say I used this same method with the old Unity UI system, so basically you rely on the UI system to do the click propagation (and stop when it hits buttons, etc), and use a fullscreen transparent background object as your "I'm clicking behind the UI" detector.

    I was going to write this when I realized you wrote the post - we were literally in the same office dealing with the same problem :D fun when that happens