How to stop raycast by ui

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.

 private void LeftClicked(InputAction.CallbackContext obj)
        {
            RaycastHit hit;
            var layerClickables = LayerMask.NameToLayer("Clickables");
            Vector3 coor = Mouse.current.position.ReadValue();
            if (Physics.Raycast(mainCamera.ScreenPointToRay(coor), out hit))
            {
                if (hit.transform.gameObject.layer == layerClickables)
                {
                    var clickable = hit.collider.GetComponent<IClickable>();
                    if (clickable != null)
                    {
                        clickable.OnLeftClick();
                    }
                }
            }
        }

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.


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

1 Like

Thank you for your answer, I am looking for link you sent and i dont like any of answers from there :smile: every single one looks terrible. Creating some “fake” objects and so on.

What solution you using?

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.

// From: https://answers.unity.com/questions/801928/46-ui-making-a-button-transparent.html?childToView=851816
//
// Touchable component (put in Extensions usually)
//
//    1. make a Button in the normal way
//    2. delete the "Text" GameObject which comes below a Button as standard
//    3. delete the "Image" which comes on a Button as standard
//    4. drop this script, InvisibleGraphic.cs, on to the GameObject with the Button
//    5. respond to button clicks on this invisible thing the same way as any other Button

using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;

#if UNITY_EDITOR
using UnityEditor;
#endif

public class InvisibleGraphic : Graphic
{
    public override bool Raycast(Vector2 sp, Camera eventCamera)
    {
        //return base.Raycast(sp, eventCamera);
        return true;
    }

    protected override void OnPopulateMesh(VertexHelper vh)
    {
        // We don't want to draw anything
        vh.Clear();
    }

    protected override void OnFillVBO(List<UIVertex> vbo)
    {
        //base.OnFillVBO(vbo);
    }

#if UNITY_EDITOR
    [CustomEditor(typeof(InvisibleGraphic))]
    public class InvisibleGraphicEditor : Editor
    {
        public override void OnInspectorGUI()
        {
            // nothing
        }
    }
#endif
}
1 Like

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?

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.”

It IS a MonoBehaviour. Follow up the inheritance tree.

8958252--1230420--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!

You can detect whether you mouse is currently over a graphic raycast object using EventSystem.current.IsPointerOverGameObject. Latest documentation here, including an example usage: Class EventSystem | Unity UI | 1.0.0

using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;

public class MouseExample : MonoBehaviour
{
    void Update()
    {
        // Check if the left mouse button was clicked
        if (Input.GetMouseButtonDown(0))
        {
            // Check if the mouse was clicked over a UI element
            if (EventSystem.current.IsPointerOverGameObject())
            {
                Debug.Log("Clicked on the UI");
            }
        }
    }
}
1 Like

Thank you i will try that.

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.

private void LeftClicked(InputAction.CallbackContext obj)
{
    if (isPointerOverGameObject) return;
    if (Physics.Raycast(mainCamera.ScreenPointToRay(Mouse.current.position.ReadValue()), out var hit))
    {
        hit.collider.GetComponent<IClickable>()?.OnLeftClick();
    }
}
{
}

private void Update()
{
    isPointerOverGameObject = EventSystem.current.IsPointerOverGameObject();
}
1 Like
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.

2 Likes

I wish I have power to delete every YT tutorial teaching to do manual raycasts to detect clickable physics.

Add this:

Implement this:

Or overload this:

Like this:

class YourInputModule : StandaloneInputModule {
     public Dictionary<int, PointerEventData> pointerData =>
         m_PointerData;
}

…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.

1 Like

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?

No, you’re not.

I.e. it gonna decide if your pointer over UI object, and prevent interaction with world object.

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.

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.

@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

https://discussions.unity.com/t/805305/11
EventSystem should work with new input module just fine.
Have you checked interaction layers (event mask) of PhysicsRaycaster?

1 Like

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.