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. Dismiss Notice

Question How to stop raycast by ui

Discussion in 'Scripting' started by MartinMa_, Apr 18, 2023.

  1. MartinMa_

    MartinMa_

    Joined:
    Jan 3, 2021
    Posts:
    455
    Hello guys I have my Screen space - overlay canvas with buttons. Behind those buttons are clickable objects in world space.

    I want prevent that if I hover or click on my UI raycast go through. How can I do it? Can you help me please?

    I tried to set layers for my objects in world space what should be clickable and also set Graphic raycaster to ignore this layer ,but nothing helped.I am still able to click through my UI.


    Code (CSharp):
    1.  private void LeftClicked(InputAction.CallbackContext obj)
    2.         {
    3.             RaycastHit hit;
    4.             var layerClickables = LayerMask.NameToLayer("Clickables");
    5.             Vector3 coor = Mouse.current.position.ReadValue();
    6.             if (Physics.Raycast(mainCamera.ScreenPointToRay(coor), out hit))
    7.             {
    8.                 if (hit.transform.gameObject.layer == layerClickables)
    9.                 {
    10.                     var clickable = hit.collider.GetComponent<IClickable>();
    11.                     if (clickable != null)
    12.                     {
    13.                         clickable.OnLeftClick();
    14.                     }
    15.                 }
    16.             }
    17.         }
    On attached screenshots are "Ghost" object what I don't want to be clicked when I am over my UI and my Graphic raycaster what I set to Canvas, I also tried set it on every button but it didn't help.
    I also added gif.

    Animation - Gifyu

    Thanks for help in advance.
     

    Attached Files:

    Last edited: Apr 18, 2023
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,756
    Physics raycast and Physics2D raycast and Graphic Raycaster are completely different systems.

    You would need to bridge them yourself, or else handle it all in one system, such as Graphic Raycaster.

    This can be done with a single final "deepest" raycast target in your UI that is under ALL the other UI and is invisible yet "catches" all the raycast clicks.

    Any click reaching that back layer has obviously missed hitting any other buttons, so now you can simply redo the click as a physics / physics2d raycast into the scene.

    This is a handy way to make an invisible raycast target, one that has zero rendering cost but acts like an image from a clickability standpoint:

    https://answers.unity.com/questions/801928/46-ui-making-a-button-transparent.html?childToView=851816
     
    MartinMa_ likes this.
  3. MartinMa_

    MartinMa_

    Joined:
    Jan 3, 2021
    Posts:
    455
    Thank you for your answer, I am looking for link you sent and i dont like any of answers from there :D every single one looks terrible. Creating some "fake" objects and so on.

    What solution you using?
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,756
    I use that solution always.

    NOTE: The solution is ONLY for the invisible touchable thing, that's all.

    All the other work of deciding to recast is up to you based on receiving a click on that Invisible touchable thing.

    Code (csharp):
    1. // From: https://answers.unity.com/questions/801928/46-ui-making-a-button-transparent.html?childToView=851816
    2. //
    3. // Touchable component (put in Extensions usually)
    4. //
    5. //    1. make a Button in the normal way
    6. //    2. delete the "Text" GameObject which comes below a Button as standard
    7. //    3. delete the "Image" which comes on a Button as standard
    8. //    4. drop this script, InvisibleGraphic.cs, on to the GameObject with the Button
    9. //    5. respond to button clicks on this invisible thing the same way as any other Button
    10.  
    11. using UnityEngine;
    12. using UnityEngine.UI;
    13. using System.Collections.Generic;
    14.  
    15. #if UNITY_EDITOR
    16. using UnityEditor;
    17. #endif
    18.  
    19. public class InvisibleGraphic : Graphic
    20. {
    21.     public override bool Raycast(Vector2 sp, Camera eventCamera)
    22.     {
    23.         //return base.Raycast(sp, eventCamera);
    24.         return true;
    25.     }
    26.  
    27.     protected override void OnPopulateMesh(VertexHelper vh)
    28.     {
    29.         // We don't want to draw anything
    30.         vh.Clear();
    31.     }
    32.  
    33.     protected override void OnFillVBO(List<UIVertex> vbo)
    34.     {
    35.         //base.OnFillVBO(vbo);
    36.     }
    37.  
    38. #if UNITY_EDITOR
    39.     [CustomEditor(typeof(InvisibleGraphic))]
    40.     public class InvisibleGraphicEditor : Editor
    41.     {
    42.         public override void OnInspectorGUI()
    43.         {
    44.             // nothing
    45.         }
    46.     }
    47. #endif
    48. }
     
    Last edited: Apr 18, 2023
    MartinMa_ likes this.
  5. MartinMa_

    MartinMa_

    Joined:
    Jan 3, 2021
    Posts:
    455
    Thank you for providing code, but where you place it since it is not a Mono script?With Touchable you mean some interface what could be clicked?
     
  6. MartinMa_

    MartinMa_

    Joined:
    Jan 3, 2021
    Posts:
    455
    What if I return [] of objects hitted by raycast and just ignore click when this array will contain my ui button do you think it will work or button just dont count for this raycast due to reason you wrote above . "Physics raycast and Physics2D raycast and Graphic Raycaster are completely different systems."
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,756
    It IS a MonoBehaviour. Follow up the inheritance tree.

    Screen Shot 2023-04-18 at 2.56.36 PM.png

    Can you re-read the how-to-use comments at the top of the script?

    Also, re-read what I wrote in the first place. I'm not sure how I can say it any different way.

    This goes on a Button, that Button does nothing except says "Wow, you clicked on me and I'm behind EVERY other button, so you must have missed all your buttons."

    That's ALL it does.

    Now with knowledge that the click missed all other buttons, you write code to (re)do a normal Physics.Raycast!
     
  8. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    1,315
    You can detect whether you mouse is currently over a graphic raycast object using
    EventSystem.current.IsPointerOverGameObject
    . Latest documentation here, including an example usage: https://docs.unity3d.com/Packages/c...ms.EventSystem.html?q=IsPointerOverGameObject

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.EventSystems;
    4.  
    5. public class MouseExample : MonoBehaviour
    6. {
    7.     void Update()
    8.     {
    9.         // Check if the left mouse button was clicked
    10.         if (Input.GetMouseButtonDown(0))
    11.         {
    12.             // Check if the mouse was clicked over a UI element
    13.             if (EventSystem.current.IsPointerOverGameObject())
    14.             {
    15.                 Debug.Log("Clicked on the UI");
    16.             }
    17.         }
    18.     }
    19. }
     
  9. MartinMa_

    MartinMa_

    Joined:
    Jan 3, 2021
    Posts:
    455
    Thank you i will try that.
     
  10. MartinMa_

    MartinMa_

    Joined:
    Jan 3, 2021
    Posts:
    455
    Thank you this is exactly what I was looking for. Simple solution. That one from Kurt was too complicated from my POV. However thank you both for your answers. This code resolve my issue.
    Code (CSharp):
    1.  
    2. private void LeftClicked(InputAction.CallbackContext obj)
    3. {
    4.     if (isPointerOverGameObject) return;
    5.     if (Physics.Raycast(mainCamera.ScreenPointToRay(Mouse.current.position.ReadValue()), out var hit))
    6.     {
    7.         hit.collider.GetComponent<IClickable>()?.OnLeftClick();
    8.     }
    9. }
    10. {
    11. }
    12.  
    13. private void Update()
    14. {
    15.     isPointerOverGameObject = EventSystem.current.IsPointerOverGameObject();
    16. }
    17.  
     
    Last edited: Apr 19, 2023
    Kurt-Dekker likes this.
  11. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,883
    Code (CSharp):
    1. hit.collider.GetComponent<IClickable>()?.OnLeftClick();
    Just a small reminder that you shouldn't use null conditional operators with anything inheriting from
    UnityEngine.Object
    as good practice.

    Use
    TryGetComponent<T>(out T)
    instead.
     
    Kurt-Dekker and MartinMa_ like this.
  12. Elhimp

    Elhimp

    Joined:
    Jan 6, 2013
    Posts:
    71
    I wish I have power to delete every YT tutorial teaching to do manual raycasts to detect clickable physics.

    Add this:
    https://docs.unity3d.com/2018.1/Documentation/ScriptReference/EventSystems.PhysicsRaycaster.html
    Implement this:
    https://docs.unity3d.com/2018.1/Documentation/ScriptReference/EventSystems.IPointerClickHandler.html
    Or overload this:
    https://docs.unity3d.com/2018.1/Doc...rence/EventSystems.StandaloneInputModule.html
    Like this:
    Code (CSharp):
    1. class YourInputModule : StandaloneInputModule {
    2.      public Dictionary<int, PointerEventData> pointerData =>
    3.          m_PointerData;
    4. }
    ...to get pointer data, including exact object (with or without interface) currently under pointer.

    EventSystem gonna do the rest in exact order you're expecting it.
     
    Madgvox likes this.
  13. MartinMa_

    MartinMa_

    Joined:
    Jan 3, 2021
    Posts:
    455
    This doesn't make sense. How does it help with my original issue with your suggestion both button and my world gameobject will have interface IPointerClickHandler implemented am i right?
     
    Last edited: Apr 20, 2023
  14. Elhimp

    Elhimp

    Joined:
    Jan 6, 2013
    Posts:
    71
    No, you're not.
    I.e. it gonna decide if your pointer over UI object, and prevent interaction with world object.
     
  15. StarBornMoonBeam

    StarBornMoonBeam

    Joined:
    Mar 26, 2023
    Posts:
    209
    I like your unity hub icon. It's a lot like my favorite website Moonbeam. Well actually since I invested in a Chinese phone I have not been on such sites in a number of many weeks. As iphone has encouraged a huge addiction. I will warn you that it is funny your icon. But also it is bad for being a based off a rude website. But I agree with you YouTube needs deep heavy ghost censorship of these tutorial makers they shouldn't even know that that exist. It should be hard for them to tell if the even exist in this world is what I'm saying. They are the most frustrating human beings on this planet the tutorial maker. Particularly the young ones who talk fast and are excited to make your acquaintance and talk a mountain out of a molehill.

    Anyways don't use that websites logo with your art it's a degrade of yourself we should not be proud of the things we've seen on those websites and the volume that we've seen it In. Those are suppose to be some people's private cultural moments and the website provides window to eavesdrop even if the intended recipient was always intended to eaves.
     
  16. MartinMa_

    MartinMa_

    Joined:
    Jan 3, 2021
    Posts:
    455
    I will try that but but i want my pointer interact with world object too but only when it is not over ui.I always pref. use things already invented by Unity over my own.
     
  17. MartinMa_

    MartinMa_

    Joined:
    Jan 3, 2021
    Posts:
    455
    @Elhimp Can you please tell me what I am missing here?

    Clicks - Gifyu

    I added interface to class and Physic raycaster to GO where is camera but if i click not Debug message.

    In documentation is just " For click detection on non-UI GameObjects, ensure a PhysicsRaycaster is attached to the Camera."

    I Think problem could be that i cannot use Standalone input module since i am using new Input module system, it force me to use InputSystemUiModule instead
     

    Attached Files:

    Last edited: Apr 20, 2023
  18. Elhimp

    Elhimp

    Joined:
    Jan 6, 2013
    Posts:
    71
    MartinMa_ likes this.
  19. MartinMa_

    MartinMa_

    Joined:
    Jan 3, 2021
    Posts:
    455
    I have not any special layer settings using default, it is working now issue was in masks i am not rly sure how it work so i tried change it and it is working now ty. This is nice approach I can delete most of my code related to these rays.
     
    Last edited: Apr 20, 2023