Search Unity

Checking if certain touch is over certain UI element

Discussion in 'Scripting' started by JaviOverflow, May 22, 2015.

  1. JaviOverflow

    JaviOverflow

    Joined:
    May 22, 2015
    Posts:
    12
    Hello,

    My goal is to be able to track a touch that starts touching a certain UI element. In order to do so, I've coded this piece of code.

    Code (CSharp):
    1. public class SquareController : MonoBehaviour {
    2.  
    3.     Text mText;
    4.     RawImage mRawImg;
    5.     int mTrackID;
    6.  
    7.     void Start () {
    8.         mText = GetComponentInChildren<Text>();
    9.         mText.text = "Hellooo";
    10.         mRawImg = GetComponentInChildren<RawImage>();
    11.     }
    12.  
    13.     void Update () {
    14.         // If we are not tracking any touch, get one
    15.         if (mTrackID != null){
    16.             foreach (Touch t in Input.touches){
    17.                 if (t.phase == TouchPhase.Began && t.isOverMyRawImg()) {
    18.                     mTrackID = t.fingerId;
    19.                 }
    20.             }
    21.  
    22.         } else {
    23.             // Look for the tracking touch
    24.             bool found = false;
    25.             foreach (Touch t in Input.touches){
    26.                 if (t.fingerId == mTrackID){
    27.                     found = true;
    28.  
    29.                     // do something with tracked touch
    30.                     mText.text = "Square is being touched";
    31.                 }
    32.             }
    33.  
    34.             // If touch is no longer available, wait for new touches
    35.             if (!found){
    36.                 mTrackID = null;
    37.                 mText.text = "You are not touching the square";
    38.             }
    39.         }
    40.     }
    41. }
    My problem is about implementing a function that returns true whether the current checked touch is over the square.

    I thought that getting the absolute coordinates of my RawImage on the screen and comparing them to touch coordinates could work, but I'm not sure if this is the easiest way to achieve this.

    Thanks a lot!
     
  2. MSplitz-PsychoK

    MSplitz-PsychoK

    Joined:
    May 16, 2015
    Posts:
    1,278
    Another way to do what (I think) you're trying to do is a raycast.

    Get the screen coordinates of your touch, then call camera.ScreenPointToRay(screenCoordinates) on your camera, passing in those coordinates. It will return a ray that you can send into Physics.RaycastAll(ray).

    You will need to make sure there is a collider on the object you are trying to touch. Physics.RaycastAll() will return an array of RaycastHit objects (RaycastHit[]). You can loop through that list of RaycastHits and get each gameobject you are touching through RaycastHit.transform.gameObject.

    Once you have the game object, you can do whatever else is necessary to make sure it's the game object that you want.


    Hope this helps!
     
    udubaso likes this.
  3. JaviOverflow

    JaviOverflow

    Joined:
    May 22, 2015
    Posts:
    12
    Gambit MSplitz thanks for your answer!

    I tried your solution and it seems not to work. This is the piece of code I wrote for the function.

    Code (CSharp):
    1. bool isOverMyRawImg(Vector2 c) {
    2.         Ray ray = Camera.current.ScreenPointToRay(c);
    3.         return Physics.RaycastAll(ray).Length > 0;
    4. }
    (I wrote > 0 in order to detect anything, not only the raw image)

    The problem might be that you can't properly use (or at least from my experience) physics colliders in GUI elements so ray can't detect these elements.
     
  4. MSplitz-PsychoK

    MSplitz-PsychoK

    Joined:
    May 16, 2015
    Posts:
    1,278
    I'm not sure about the old Unity UI, but the new Unity 4.6 UI should work just fine with colliders.

    - Make sure there is a collider on the things you want to touch
    - Make sure the camera you are calling ScreenPointToRay() on is the camera that sees the objects you are touching
    - Make sure the vector you pass into ScreenPointToRay() is a screen space position not clip space. Screen space will have a positive x and y between 0 and the width and height of your game screen respectively

    I'm not sure what else could be wrong, though in my experience ScreenPointToRay() takes in a vector3, so I don't know how you're sending in a vector2. If you're still stuck, call Debug.DrawRay() and pass in your ray to make sure your ray actually intersects the object you want to touch.
     
  5. KyleStank

    KyleStank

    Joined:
    Feb 9, 2014
    Posts:
    204
    You can inherit these:

    Code (csharp):
    1. public class MyClass : MonoBehaviour, IPointerDownHandler, IPointerEnterHandler
    Then add a method like these:
    Code (csharp):
    1. public void OnPointerDown(PointerEventData data)
    2. {
    3.     print(string.Format("{0} clicked!", transform.name));
    4. }
    5.  
    6. public void OnPointerEnter(PointerEventData data)
    7. {
    8.     print(string.Format("{0} entered!", transform.name));
    9. }
    See: http://docs.unity3d.com/ScriptReference/30_search.html?q=IPointer