- Home /
How to prevent clicking Gameobjects behind a Canvas/Panel?
Goo day all. (sry if bad english)
I have a scene with GameObjects that can be clicked. I also have an info panel at the bottom of the screen.
This panel have a hide/show function and it works well. The problem is when the panel is active, if the player click on the panel and ther is a gameobjects behind the panel, the gameobject is also clicked, and ofc, I dont want that. I need the gameobjjects to be "not clikable" if they are behind the panel.
How i prevent the click to "reach" the gameobject if there is a panel in front?
Maybe raycast is the solution? I've never used it... some another way to do it?
Thanks in advance!
I believe only buttons can be clicked at runtime. If this is correct, click on button and uncheck "interactable".
Hello @bolkay
That is not true... everything with a collider can be clicked with On$$anonymous$$ouseDown() function
Answer by haruna9x · Sep 23, 2017 at 10:46 AM
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");
}
}
}
Thanks!
It works!, i had to do it negative of course, but it worked!
if ( ! EventSystem.current.IsPointerOverGameObject())
{
DoSomethingBecauseIclikedTheObject()
}
Basically you return or do nothing when the click happens on the panel.
if (EventSystem.current.IsPointerOverGameObject())
{
//It means clicked on panel. So we do not consider this as click on game Object. Hence returning.
return;
}
else{
//clicked directly on game object.
}
This doesn’t work, at least not in 2018.4. I have this exact script attached to a game object with a canvas backdrop, and I can still click through to game objects behind it, even with “Raycast Target” checked.
This is working for me in 2019.4. How are you using this particular piece of code?
This the only thing that worked for me, Jason explains it here: https://www.youtube.com/watch?v=rATAnkClkWU&ab_channel=JasonWeimann
Answer by frankslater · Sep 23, 2017 at 12:24 PM
I don't recommend checking for and analyzing mouse clicks in Game Objects' Update(). All objects that have the script are going to be checking and analyzing mouse clicks every single frame. That isn't a good practice and will quickly cause performance problems. There are different callbacks for input events that you can use.
Better to use IPointer Handlers like IPointerClickHandler, IPointerDownHandler, IPointerUpHandler and related callbacks.
Your clicks won't be registered through other objects.
If you use these, you only need to make sure that your panel is a Raycast Target (it is by default), and it's going to block out the Raycast from these callbacks. They also work better on touch screens than OnMouse callbacks.
(Clickable objects are always Raycast Targets. Others you might set just to block raycasts when over something.)
If you have something like this on your Game Objects, it won't be fired if a button, or panel, or anything else was clicked while your Game Object is behind:
using UnityEngine;
using UnityEngine.EventSystems;
public class TouchForceExample : MonoBehaviour, IPointerClickHandler {
public void OnPointerClick(PointerEventData data) {
// This will only execute if the objects collider was the first hit by the click's raycast
Debug.Log(gameObject.name + ": I was clicked!");
}
}
Another Example:
using UnityEngine;
using UnityEngine.EventSystems;
public class TouchForceExample : MonoBehaviour, IPointerUpHandler, IPointerDownHandler {
public void OnPointerDown (PointerEventData data) {
ExamplePhysicsScript.instance.ForceIncrement ();
}
public void OnPointerUp (PointerEventData data) {
ExamplePhysicsScript.instance.ForceSet ();
}
}
You can also use PointerEventData in interesting ways. For example to track the position of the pointer while it's down (so the user can drag something), or just to get a vector from pointer down to pointer up with PointerEventData.position.
Hello @frankslater !
$$anonymous$$aybe this could work, but with my code is not the perfect solution, is better to check if a UI was clicked. thx anyway :D
Not that this will only work with GameObject's within the canvas since they are the ones monitored by the EventSystem. IPointer* interfaces are in the EventSystems namespace so if you are trying to use this on other GO's, you wont get the event.
Also, the comment on raycasts being expensive is very misleading as it really depends on the depth of the game and its mechanics.
One way of improving is to have a reference to the RaycastHit and use that as the out variable, that way you save performance from GC per frame per object.
Answer by Jon_Olive · Jan 26, 2019 at 05:37 PM
I realise this is an old thread - but I just found a simple solution: I made a transparent panel the size of the UI canvas. I arrange for everything I want to mask to be above it in the hierarchy and everything I don't to be below (a popup input dialogue for example). So when I call up the input dialogue I also enable the transparent panel. Job done!
Answer by omgbot · Apr 29, 2019 at 02:35 PM
For each object to hang such a code in the UPDATE is just a nightmare.
SUPER CODE :) Only MouseUP !!
private void OnMouseUp()
{
ClickUI = false;
if (EventSystem.current.IsPointerOverGameObject())
{
if (EventSystem.current.currentSelectedGameObject.name == "IcoDropDown")
{
ClickUI = true;
}
}
if(ClickUI){
Debug.Log("Click UI button");
}
}
hello this is probably a stupid question what do i define ClickUI as? @omgbot