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
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

UI-Toolkit and Raycast Block?

Discussion in 'UI Toolkit' started by Bromm, Jan 7, 2021.

  1. Bromm

    Bromm

    Joined:
    Nov 18, 2014
    Posts:
    18
    When I add ui on top of the SceneView it blocks all scene controls. Is there a way to prevent this behaviour for certain elements or for transparent elements parts?

    I failed to find a checkbox in the UI-Builder, google search didn't help me either. Maybe it can be done somehow via code?
     
    ViaPixels likes this.
  2. uMathieu

    uMathieu

    Unity Technologies

    Joined:
    Jun 6, 2017
    Posts:
    384
    Last edited: Mar 22, 2021
  3. Arkenhammer

    Arkenhammer

    Joined:
    Nov 10, 2019
    Posts:
    51
    Ooo! You can set that in USS! I'd been setting it in code because I didn't know I had another option.
     
  4. Bromm

    Bromm

    Joined:
    Nov 18, 2014
    Posts:
    18
    picking-mode="Ignore"
    seems to just make the element non-interactive, so it doesn't react to mouse events but still blocks them for the scene window :(

    Also tried adding
    picking-mode="Ignore"
    to all elements
     
    TebogoWesi and ph3rin like this.
  5. Arkenhammer

    Arkenhammer

    Joined:
    Nov 10, 2019
    Posts:
    51
    Oh, PickingMode.Ignore means that a VisualElement doesn't handle a click and lets it drop fall through to the element behind it. For me the old input system (e.g. Input.GetMouseButton(0) in the Update loop of a game object) always sees clicks whether the UIToolkit EventSystem handles it or not so UIToolkit documents never block clicks.
     
  6. Bromm

    Bromm

    Joined:
    Nov 18, 2014
    Posts:
    18
    I assume SceneView not using
    Input.
    but something like
    Event.current
    . And maybe VE catches that event... don't know.
     
  7. Maverick

    Maverick

    Joined:
    Dec 18, 2009
    Posts:
    225
    Seems there is no "picking-mode" in uss. I'm getting warnings in unity.
    Am I doing something wrong?
     
  8. uMathieu

    uMathieu

    Unity Technologies

    Joined:
    Jun 6, 2017
    Posts:
    384
    You're right Maverick, I was mistaken: picking-mode is available through uxml, not uss. Sorry for the confusion.
     
  9. qwert024

    qwert024

    Joined:
    Oct 21, 2015
    Posts:
    43
    Hello,
    Sorry to bring this thread up!
    I was wondering if there is a way to detect which UI element I hit with raycast (I want to know if I hit button01, button02, panel01, etc.)
    In the below example I set picking-mode of "screen" and "menu" to ignore
    And with the following code, when my mouse is on "btn01" or "btn02" I can get a RaycastResult
    However result.gameObject.name is always "PanelSettings".
    I was wondering if there is a way to know which specific UI element is being hit?
    It would be so great if someone could shed some light on this!

    Code (CSharp):
    1. void Update()
    2.     {
    3.    
    4.         PointerEventData pointer = new PointerEventData(EventSystem.current);
    5.         pointer.position = Mouse.current.position.ReadValue();
    6.         List<RaycastResult> raycastResults = new List<RaycastResult>();
    7.         // this can hit ui with "picking mode" set to "position"
    8.         EventSystem.current.RaycastAll(pointer, raycastResults);
    9.      
    10.         Debug.Log($"count: {raycastResults.Count}");
    11.         if (raycastResults.Count > 0)
    12.         {
    13.             foreach (RaycastResult result in raycastResults)
    14.             {
    15.                 Debug.Log($"name: {result.gameObject.name}");
    16.             }
    17.         }    
    18.     }
     
    flogskin likes this.
  10. edmund_munday

    edmund_munday

    Joined:
    Jan 12, 2021
    Posts:
    3
    Posting this in a few places because it's been asked a bunch and nobody seems to have an elegant solution for it.

    The key to handling the new UI element system is treating it like Web Development. That means understanding that everything is event-driven and there are events for literally everything. These events can also have callbacks registered to them which let you change your logic based on what's going on.

    Some people have posted solutions to this problem that involve doing things like checking if the cursor is over a UI element every single frame, and storing that in memory to reference in your other logic. While this CAN work, it would be absolutely disgusting for performance.
    What you should be doing instead is using event listeners and callbacks to get the same effect, but without the performance impact.

    Let's say you have a menu panel that you want to block interaction with the area behind it. That panel can have text, buttons, whatever you want, it's not relevant. What is relevant is that you don't want your mouse to interact with the game world when it is over that element.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UIElements;
    3.  
    4. public class MenuBackgroundPanel : MonoBehaviour
    5. {
    6.     // variable to hold the panel ui element
    7.     private VisualElement _menuBackgroundPanelUiElement;
    8.  
    9.  
    10.     // Callback to be called when the Mouse enters the panel.
    11.     private void MouseEnterCallback(MouseEnterEvent evt)
    12.     {
    13.         // check if the target of the event is the background element (because UI events "bubble" through the UI tree, so it could be an event for a different element).
    14.         if (evt.target == _menuBackgroundPanelUiElement)
    15.         {
    16.             Debug.Log("Mouse has entered the panel");
    17.             Debug.Log("Update some kind of global flag that says the mouse is now over the UI.");
    18.         }
    19.     }
    20.  
    21.     // Callback to be called when the Mouse leaves the panel.
    22.     private void MouseLeaveCallback(MouseLeaveEvent evt)
    23.     {
    24.         // check if the target of the event is the background element (because UI events "bubble" through the UI tree, so it could be an event for a different element).
    25.         if (evt.target == _menuBackgroundPanelUiElement)
    26.         {
    27.             Debug.Log("mouse has left the panel");
    28.             Debug.Log("Update some kind of global flag that says the mouse has left the UI.");
    29.         }
    30.     }
    31.  
    32.     // Method that registers the MouseEnterCallback on the MouseEnter UI event.
    33.     private void RegisterMouseEnterCallback()
    34.     {
    35.         // Registers a callback on the MouseEnterEvent which will call MouseEnterCallback
    36.         _menuBackgroundPanelUiElement.RegisterCallback<MouseEnterEvent>(MouseEnterCallback);
    37.     }
    38.  
    39.     // Method that registers the MouseLeaveCallback on the MouseLeave UI event.
    40.     private void RegisterMouseLeaveCallback()
    41.     {
    42.         // Registers a callback on the MouseLeaveEvent which will call MouseLeaveCallback
    43.         _menuBackgroundPanelUiElement.RegisterCallback<MouseLeaveEvent>(MouseLeaveCallback);
    44.     }
    45.  
    46.     private void Start()
    47.     {
    48.         // query and store the panel ui element
    49.         VisualElement root = GetComponent<UIDocument>().rootVisualElement;
    50.         _menuBackgroundPanelUiElement = root.Q<VisualElement>("menu-background-panel");
    51.  
    52.         // register callbacks for MouseEnter and MouseLeave events on the panel element
    53.         RegisterMouseEnterCallback();
    54.         RegisterMouseLeaveCallback();
    55.     }
    56. }
     
  11. restush96

    restush96

    Joined:
    May 28, 2019
    Posts:
    120
  12. CaseyHofland

    CaseyHofland

    Joined:
    Mar 18, 2016
    Posts:
    553
    This is happening to me as well. It's really annoying, I'm trying to make a compact PropertyDrawer and this one thing is making it near-impossible if I don't want to hack together a bunch of pixel values (and I don't it looks awful).

    @uMathieu is there a way to ignore object picking within the Inspector? In my case I want to overlay a field on top of a foldout, and then disable the fields label. But setting the label to
    DisplayStyle.None
    stretches the field out over the entire width of the Inspector. Setting the label to
    Visibility.Hidden
    looks PERFECT... but it blocks my foldout so I cannot click it.

    I've tried for a looong time to just fiddle it with 'width' but I cannot for the life of me find out what field width is supposed to be. Keep in mind it needs to respect indent levels with lists and such.
     
  13. CaseyHofland

    CaseyHofland

    Joined:
    Mar 18, 2016
    Posts:
    553
    Found another way:

    Code (CSharp):
    1. var foldout = new Foldout();
    2. var overlay = new PropertyField(myProperty, myLabel);
    3. overlay.style.position = Position.Absolute;
    4. overlay.style.width = new Length(100f, LengtUnit.Percent);
    5. overlay.style.left = 18f;
    6. overlay.style.paddingRight = 18f;
    7.  
    8. var root = new VisualElement();
    9. root.Add(foldout);
    10. root.Add(overlay); // In this order!!
    This will use the label of the overlay, making only the arrow-part of the foldout clickable. Not preferred, but 10 million times better than a crooked editor.
     
  14. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,793
    Seeing this regression back to web styled implementation of a UI reminds me of why I definitely prefer the approach of Unity UI. USS and UXML are a PITA and you have to juggle docs and waste developer memory to work with. Any UI should be component based WYSIWYG with configs as part of the UI object. Other than that your system will waste devs time.
     
    alexandervitkov and horatiu665 like this.