Android touches pass through UI elements
Is there a way to prevent Android touches to pass through UI elements on a canvas? I'm using Unity 5.2.1f1.
Possible answers for non-tile map uses http://answers.unity3d.com/questions/784617/how-do-i-block-touch-events-from-propagating-throu.html
Setup
2d game.
An overlay canvas with buttons.
A gameobject input handler that checks for world input on the update method. Input through this method checks the world for interactivity.
Why do I check for world objects based at a location? I'm using a tile map that dynamically loads tiles and the system has a simple method to convert a world location to a specific tile location on the map. The tiles do not have any events on them.
Desktop and Editor Work
Grab from the update method Input.mousePosition if the pointer is not over a game object.
if( EventSystem.current.IsPointerOverGameObject() )
return;
Android Build Doesn't Work
Grab the first touch. If it has ended check if the pointer is over an object.
Touch touch = Input.GetTouch(0);
if( touch.phase == TouchPhase.Ended )
{
//prevent touch through
if( EventSystem.current.IsPointerOverGameObject(touch.fingerId) )
return false;
vec = touch.position;
return true;
}
I've also tried looping over touches. IsPointerOverGameObject appears to be useless for preventing Android touches from passing through UI canvas objects.
Android Build Work Around
The only way I've found how to work around this issue, thanks to Fattie, is to check for a selected gameobject in the event system.
if( EventSystem.current.currentSelectedGameObject != null ) return false;
Is there a better way to do this? The only tutorials I've seen that might relate require an event interface for the tiles in the tile map and any game object agents acting "on top" of the tile map.
I've spent about my whole afternoon reading forum posts about this issue and have not come way with a better solution.
Some discussions
http://forum.unity3d.com/threads/ui-not-working-5-1-1-5-2-0b1.339462/#post-2195414
http://forum.unity3d.com/threads/upgrading-to-unity-5-2-ui-problem-with-raycast-target.353586/
http://answers.unity3d.com/questions/784617/how-do-i-block-touch-events-from-propagating-throu.html
Answer by karjalan · Jan 27, 2016 at 02:14 AM
using UnityEngine.EventSystems;
using System.Collections.Generic;
private bool IsPointerOverUIObject() {
PointerEventData eventDataCurrentPosition = new PointerEventData(EventSystem.current);
eventDataCurrentPosition.position = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
List<RaycastResult> results = new List<RaycastResult>();
EventSystem.current.RaycastAll(eventDataCurrentPosition, results);
return results.Count > 0;
}
I found this solution from _metiss
Using a simple if statement lets you check if you're over any ui element or the main game.
if (!IsPointerOverUIObject())
It's a very annoying problem and it seems like the forums are filled with part or incorrect answers, and I'm not expert but I have found that this specific function works best for me.
Hey danishkumar
It's been a while and I can't test it at the moment, but if you play around in the function with some Debug.Log();
functions you should be able to find it.
I imagine the results array should contain what you've touched. Note it's an array because you can/do essentially touch multiple things at once.
can't thank you enough for this... I've been searching for a sollution all day, I was pretty close, found a lot of suggestions involving EventSystem, but yours is the only one that worked. Thank you so much :)
Answer by Binary42 · Jan 27, 2016 at 09:24 PM
if (EventSystem.current.IsPointerOverGameObject() ||
EventSystem.current.currentSelectedGameObject != null) {
return;
}
Works for me here on Android ( with Unity 5.3.1f1 )
This worked for me with my Android vuforia project, the other solutions made the tracking stop working entirely for some reason.
God bless you man! Two days reading entire threads of discussion and trying to find a solution for my specific case. Thanks!
Answer by DalamarTD7 · Jan 21, 2016 at 07:11 AM
using UnityEngine.EventSystems;
Vector2 touchPos;
public GraphicRaycaster GR;
void Update()
{
if(Input.touchCount > 0)
{
if(Input.GetTouch(0).phase == TouchPhase.Began)
{
PointerEventData ped = new PointerEventData(null);
ped.position = Input.GetTouch(0).position;
List<RaycastResult> results = new List<RaycastResult>();
GR.Raycast(ped, results);
if(results.Count == 0)
{
// YOUR CODE HERE
}
}
}
}
I just had to share this solution. I am using touch controls for android to move selected units by simply touching a spot on the screen. Like many other people I had issues with my touches going through my UI. I could not find a working solution on the forums but I found one in the "yonder". Any code that you put in the designated if statement will return true only if you're not pressing on a GUI element. You can similarly return the UI elements under your touch. I selected the only GraphicRaycaster in my scene from my one canvas object in the inspector. I worked out my solution from info found here. Check it out @ecesis_llc
Hey Dalmar, this looks promising however I'm currently struggling to get it working, it seems when I use your code I get (count = 0) for everything I touch, buttons, panel, game objects...
This is a problem I'm having as well, my current game moves by touching the screen making using buttons break the flow of it.
As a side-note I added the following dependencies. To get access to some of those tools/methods.
using UnityEngine.UI;
using System.Collections.Generic;
Five years late but this helped me out immensely! I touch the right and left side of my screen to move the character along the x axis and whenever I would try to touch the pause button in the top left of the screen my player would move to the left. I plugged this piece of code into my player movement script and dropped the pause button panel into the designation for the GraphicRaycaster and it works flawlessly. I was stuck on this problem for at least 2 hours before stumbling across this plug and play solution. Thanks for sharing!
Answer by Rogelio · Mar 20, 2017 at 06:55 AM
I made this solution:
using UnityEngine.EventSystems;
...
if (EventSystem.current.currentSelectedGameObject == null) {
//not toch UI
}
if you have a panel or something you want block only add button component, and changue color tint to none
Answer by Redwolve · May 07, 2016 at 03:55 AM
So I haven't been able to find a way that makes more sense than this, but hey for now it works rather well for me.
So I was having the same problem, clicking on my UI would cause things to be built underneath the UI where the player did not want things to show up. So here is what I did.
On the Camera that is used for said RayCasting I created a 3D Cube Object and made it the child of the camera. I made it fit as snug as I could to the area in which I wanted blocked, now obviously you can use whatever shape you want. So now you don't want this to be an eyesore right, so just delete or diable the mesh rendered and set the Z axis to 0. This will cause the raycast to hit the ghosted 3D Collider before anything else. Hope it helps at least until a better solution is found for ya.
Your answer
Follow this Question
Related Questions
What is the best way to implement a more responsive custom drag event with Scroll Rect? 0 Answers
Massive lag spike on first Input.GetTouch with nothing on scene but one script (Android) 2 Answers
UI button events not working on android 3 Answers
How to interact with UI elements and oculus touch controller? (No Gaze!) 3 Answers
Input Field Not Interactible 0 Answers