Canvas Group not blocking raycasts even when option is enabled

I created an empty game object and placed all my UI elements needed for my inventory inside of it and attached a Canvas Group component to that empty so I can easily hide/reveal it in script without disabling it. One of the options in the Canvas Group is ‘Block Raycasts,’ this gets enabled in my script when the UI is shown, but it won’t block raycasts! I’m still able to click on objects through the UI and I can’t figure out why. Help would be appreciated!

Hide/Reveal UI

        if (Input.GetKeyDown(KeyCode.Tab))
        {
            if (!inventoryOpen)
            {
                inventoryOpen = true;
                inventoryUI.alpha = 1.0f;
                inventoryUI.blocksRaycasts = true;
            }
            else
            {
                inventoryOpen = false;
                inventoryUI.alpha = 0.0f;
                inventoryUI.blocksRaycasts = false;
            }
        }

Interaction Script

       Ray ray = cam.ScreenPointToRay(Input.mousePosition);
        if (Input.GetMouseButtonDown(0)) // Left click
        {
            if (Physics.Raycast(ray, out hit, interactDistance))
            {
                Vector3 rayDirection = playerPos.position - hit.point;

                InteractableObject interactableObject = hit.collider.GetComponent<InteractableObject>();

                if (interactableObject != null) // If the player clicked on an object that has an interactableObject component on it, interact with it
                {
                    InteractWithObject(interactableObject);
                }
            }
        }
1 Like

i think it doesnt block the usual Physics.Raycasts,
probably this would work
https://docs.unity3d.com/ScriptReference/EventSystems.PhysicsRaycaster.html

in 5.6 i was testing for ui elements with these, before doing raycast next

if (eventSystem.IsPointerOverGameObject()) return;
if (eventSystem.currentSelectedGameObject != null) return;

*tested in 2020.2.2f1 still works

1 Like

Ah! I’ll just add another condition to my interaction script to check if the inventory is not open, that should do the trick!

Note that a CanvasGroup will never block raycasts on its own; you still need some component that acts as a raycast target. That flag can be used to make that object and all its children stop blocking raycasts when they would normally block them, but it doesn’t cause them to be blocked if they normally wouldn’t be.

If you want to create a “shield” that blocks clicks from hitting things behind it, try using an Image with 100% transparency.

1 Like

Try putting a Graphic Raycaster on your canvas group.

11 Likes

this worked

1 Like

None of these solutions worked for me in 2018.4 — I had to hack my own method with a Boolean set and cleared on enables and disable of the canvas, and have the game objects directly underneath check for it before registering clicks.

I don’t understand why this hasn’t been fixed yet — people should not have to bend over backwards to hack solutions like these together to stop canvas clicks from going through to physics objects behind them — it’s a no-brainer that something like that should never happen in a professional development environment. Please update the canvas system, as it’s a hot mess overall.

I don’t mean to be rude, but our company is a pro paying customer and the number of issues we’ve had with trying to reconcile the Canvas system and the game objects has gotten out of control.

16 Likes

I have not been able to get any of these solutions working in 2019.4. It seems as though this functionality has changed (or broken) Now, what I have to do is run two separate ray casts. A raycast from the canvas’s GraphicsRaycaster to detect UI and then a separate raycast from Physics for the 3D world. It feels excessive, like north of 20 lines of code in a shortcut to get this separation to work in the code, when it used to be 1 line of code.

1 Like

None of the above solutions worked for me in 2019.4.0f1 unfortunately. I added a dummy button component and set it to non interactive. That worked for me.

1 Like

Can also confirm that none of the above methods worked in 2019.4.0.f1

I had a game object with the following components:
Canvas
Canvas Group
GraphicsRayCaster

I couldn’t get the above configuration of components to work with any variation of settings. This feels like a bug.

Adding a transparent Image as with “Raycast Target” set to True worked for me.

fyi, I am using PointerEventData argument in OnEndDrag; e.g. eventData.pointerCurrentRaycast;

I found a bug in this (2019.4 LTS - the current live version of Unity):

  1. GraphicsRaycaster ignores all meshes, it only uses the Physics Colliders on objects (which is wrong, by definition - but it’s unlikely Unity will ever fix this particular bug)
  2. In addition: GraphicsRaycaster is evaluated at the end of the frame, and if you disable or remove your Collider during the frame, while processing e.g. Unity’s OnMouseDown event … Unity will incorrectly re-run the raycast using the mid-frame-updated data, and fail to block the raycasts.

I very much doubt Unity will fix any of this, but I’ll try and make a small repro and submit a bug for it.

4 Likes

You could put a check in your ray cast function to make sure no game object is highlighted by the event system. I think its stored in a static variable in EventSystem.SelectedGameObject.

Any updates on this?

Mobile is a disaster trying to block UI raycasts through UI elements. It only works for touch down… not up or dragging.

1 Like

Having the same problem on 2019.4.1f :frowning: Not fun !

2 Likes

2020.1.8f - same story

Still running into this same issue with 2019.4.18. Can we get an update from Unity on a bug fix for this or at the very least a workaround? I’ve been trying to get this simple drag / drop working for days, it really shouldn’t be this difficult.

Unity’s documentation Canvas Group | Unity UI | 1.0.0
states that

  • Making one or more UI elements not block mouse events by placing a Canvas Group component on the element or one of its parents and setting its Block Raycasts property to false

My setup is an Image gameobject as parent with a button as child using Event Trigger system with OnPointerDown and the behaviour is the opposite:

If Block Raycasts is ticked(true?) then it allows the raycasting and if unticked then I can’t click on the button.

2 Likes

After a lot of frustation I have come to the conclusion that for a raycast to be properly blocked by a screenspace canvas and not hit the gameobjects in the scene, you need:

  1. A UI element that can block raycasts, like an image or a textmesh, set to block.

For screenspace UI, it doesn’t matter if your blocking objects are in the UI layer and that layer is excluded by the raycast layermask (presumably, because the screenspace is not the worldspace where physics happens), so what you also need is:

  1. Check EventSystem.current.IsPointerOverGameObject() in the code that throws the raycast. This is part of the UnityEngine.EventSystems namespace.

Because Unity loves to confuse us, note that the horribly named IsPointerOverGameObject means that the pointer is over a UI element object and not just any GameObject, a behavior which is not documented anywhere I looked and had to deduce through experiment.

So this should work:

using UnityEngine;
using UnityEngine.EventSystems;

public class MouseClicker : MonoBehaviour
{
    [SerializeField] float maxRayDistance = 10;
    [SerializeField] LayerMask collidableLayers;

    void Update()
    {
        if (Input.GetMouseButtonDown(0)) // 0 is left click
        {
            Ray ray = screenCamera.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out RaycastHit hit, maxRayDistance, collidableLayers) && !EventSystem.current.IsPointerOverGameObject())
            {
                // code here only executes if the raycast hit an object in a valid layer and is NOT over a UI object
            }
        }
    }
}

It’s a pain that Unity doesn’t have some clear explanation of the chaos that is its GUI system, it drives me crazy.

I’m thinking of creating some methods that wrap Unity’s Raycast to have this check done so I don’t have to remember this all the time…

10 Likes

It’s OK - the team has moved on now, they’ve created a whole new UI system with a fresh set of major bugs for us to enjoy! :slight_smile:

(but being serious: there are still at least a few Unity staff fixing bugs in the current UI, even if not many - I’ve logged bugs in the past 3-4 months that have been accepted and fixed in latest Unity. And it appears to be a different team that’s making UIToolkit)

1 Like

Thank you so much! I ran into this problem in 2020.3.4 and I only had to add a Graphics Raycaster to my UI Image and then add the code you provided.

I wonder what’s the use for “Blocking Objects” and Blocking Masks, if changing these options does not actually block anything :eyes:

1 Like