Block a Raycast at the UI Layer???

For this post, I’ve put the below Unity project up on GitHub, link is here.

I’m using Unity 2022.2.10f1. In my game, I have a UI Button on the UI Layer and a clickable Sprite on the Default UI Layer. (I’m using the below images for the button and sprite, respectively):

What could be simpler? In Unity, I create the following hierarchy:

And arrange them in the scene as follows:

The Sprite has a 2D Box Collider component where the boundaries of the sprite match the boundaries of the sprite. Further, the sprite has this C# script:

  • using UnityEngine;
  • public class TestSprite : MonoBehaviour
  • {
  • void OnMouseDown()
  • {
  • Debug.Log(“Sprite Clicked!”);
  • }
  • }

And the button has this script:

  • using UnityEngine;
  • using UnityEngine.EventSystems;
  • public class ButtonScript : MonoBehaviour, IPointerClickHandler
  • {
  • public void OnPointerClick(PointerEventData eventData)
  • {
  • Debug.Log(“Button Clicked!”);
  • }
  • }

Again, the button is on the UI Sorting Layer, and the Sprite is on the Default Sorting Layer.

On the UI Canvas, I’ve attached a Graphic Raycaster component:

And I’ve clicked “Raycast Target” on the Button’s Image component:

According to the online resources about Raycasts that I’ve read (like here and here and other locations), I should be good to go. A mouse click on the UI Button should NOT project a Raycast through the button to any other GameObject behind it.

Now I run the game. When I click on the button or sprite where they don’t overlap, I see the “Button Clicked!” or “Sprite Clicked!” debug messages, as I should. But when I click where sprite and button do overlap:

One click, two events, both at the same time index. Clearly, the Raycast from my mouse click is passing through the Button and hitting the Sprite. That’s not what I want. GAH!!! So frustrating.

Anyone see what I’m doing wrong? And why is this behavior the default for a UI GameObject, anyway? In what scenario would you want to click on something in the UI and have the non-UI GameObject behind it also clicked? Thank you.

FULL DISCLOSURE: I posted this message earlier, here . When I didn’t get a response, I decided to post again.

For it to work like that you need to use IPointerClickHandler or IPointerDownHandler on the sprite as well instead of OnMouseDown. You will also need a Physics2DRaycaster attached to camera so that IPointerSomethinHandler work on objects with physics colliders.

OnMouseDown is one of the builtin Unity magic methods like similar to OnEnable or Update, it doesn’t know anything about UGUI ands structure.

IPointerSomethingHandler handles are part of UGUI package. It has the code to integrate with physics colliders, but not the other way around.

Lesson here is that you can’t treat Unity as single monolith. A lot of stuff isn’t part of Unity core functionality. You need to be aware that different stuff comes from different packages and not everything is handled equally. In some ways you might as well consider them third party packages both in terms of support and the integration with other parts of Unity.

@karliss_coldwild Thanks Karliss, experience and pointers like this go a long way to helping newbies like me. I’ll read up on IPointerClickHandler, IPointerDownHandler, and Physics2DRaycaster. Thank you!

Your larger point that the different Unity components are not all tools from the same uniform toolbox is helpful perspective, too. I guess I’ll have to start tracking what components come from which package. That’s honestly quite a revelation: I was completely ignorant about this aspect of Unity. I guess one gains that wisdom through experience.