- Home /
UI buttons and touch input problem
Guys, I have one problem. I'm developing a mobile game which is a simple infinite runner. For player controls I using something like:
if (Input.touchCount > 0)
{
for (int i = 0; i < Input.touchCount; i ++)
{
Touch touch = Input.GetTouch(i);
if (touch.phase == TouchPhase.Began)
{
//Jump
}
}
}
The pause button is a UI element and when I'm pressing it player jumps but he is not supposed to. Then I've made a check with EventSystemManager.currentSystem.IsPointerOverEventSystemObject() in player code. And while testing with Unity Remote it works fine, but after building project on Android device this doesn't work, player still jumps. How to solve this problem? Maybe there is another way of checking?
Well, yeah. I found another solution. Ins$$anonymous$$d of using Input.touch, I made an invisible UI button stretched to full screen and added the following script to it:
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections;
public class PlayerInputArea : $$anonymous$$onoBehaviour, IPointerDownHandler, IPointerUpHandler {
private bool touched;
private int pointerID;
void Awake () {
touched = false;
}
public void OnPointerDown(PointerEventData data) {
if (!touched)
{
touched = true;
pointerID = data.pointerId;
}
}
public void OnPointerUp(PointerEventData data) {
if (data.pointerId == pointerID)
touched = false;
}
public bool IsTouched() {
return touched;
}
}
And then I use IsTouched() in player code. It works fine. But one thing to note: this UI button must be behind all other buttons.
I had the same issue. I created the full-screen button that triggers the gameplay action, I created the pause button and my pause button wasn't working. I came across your post and set the Z coordinates of the buttons so that pause button is in front of the action button, but it didn't work out. What worked out eventually was to set the hierarchy order so that action button is first and pause button is second, and it worked.
Answer by Krizzen · Jan 04, 2015 at 11:17 AM
I ran into this exact issue today. Apparently EventSystemManager.currentSystem.IsPointerOverEventSystemObject() always returns false in an actual APK build. The issue tracker was marked "By Design", but it definitely seems like a bug to me.
Use this code as a work around (Credit goes to MWK888, found here: http://forum.unity3d.com/threads/ispointerovereventsystemobject-always-returns-false-on-mobile.265372/ ):
/// <summary>
/// Cast a ray to test if Input.mousePosition is over any UI object in EventSystem.current. This is a replacement
/// for IsPointerOverGameObject() which does not work on Android in 4.6.0f3
/// </summary>
private bool IsPointerOverUIObject() {
// Referencing this code for GraphicRaycaster https://gist.github.com/stramit/ead7ca1f432f3c0f181f
// the ray cast appears to require only eventData.position.
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;
}
/// <summary>
/// Cast a ray to test if screenPosition is over any UI object in canvas. This is a replacement
/// for IsPointerOverGameObject() which does not work on Android in 4.6.0f3
/// </summary>
private bool IsPointerOverUIObject(Canvas canvas, Vector2 screenPosition) {
// Referencing this code for GraphicRaycaster https://gist.github.com/stramit/ead7ca1f432f3c0f181f
// the ray cast appears to require only eventData.position.
PointerEventData eventDataCurrentPosition = new PointerEventData(EventSystem.current);
eventDataCurrentPosition.position = screenPosition;
GraphicRaycaster uiRaycaster = canvas.gameObject.GetComponent<GraphicRaycaster>();
List<RaycastResult> results = new List<RaycastResult>();
uiRaycaster.Raycast(eventDataCurrentPosition, results);
return results.Count > 0;
}
Thanks for your reply, $$anonymous$$rizzen. I'll try to do something with this.
Answer by hdtnl · Feb 01, 2017 at 11:53 AM
Let try it from Unity Document: https://docs.unity3d.com/ScriptReference/EventSystems.EventSystem.IsPointerOverGameObject.html
void Update ()
{
// Check if there is a touch
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
{
// Check if finger is over a UI element
if(EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))
{
Debug.Log("Touched the UI");
}
}
}
Answer by DimitryCastex · Mar 25, 2016 at 09:32 PM
For touch input this code work for me
/// <summary>
/// Cast a ray to test if Input.mousePosition is over any UI object in EventSystem.current. This is a replacement
/// for IsPointerOverGameObject() which does not work on Android in 4.6.0f3
/// </summary>
private bool IsPointerOverUIObject(Touch t)
{
// Referencing this code for GraphicRaycaster https://gist.github.com/stramit/ead7ca1f432f3c0f181f
// the ray cast appears to require only eventData.position.
PointerEventData eventDataCurrentPosition = new PointerEventData(EventSystem.current);
eventDataCurrentPosition.position = new Vector2(t.position.x, t.position.y);
List<RaycastResult> results = new List<RaycastResult>();
EventSystem.current.RaycastAll(eventDataCurrentPosition, results);
return results.Count > 0;
}
the argument t is an element in Input.touches[]