FingerManager

From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
m (Text replace - "</csharp>" to "</syntaxhighlight>")
(update deprecated code)
Line 1: Line 1:
[[Category: Concepts]]
+
[[Category:Code Examples]]
[[Category: Controller]]
+
[[Category:Input]]
[[Category: Design Patterns]]
+
[[Category: MonoBehaviour]]
+
[[Category: C Sharp]]
+
[[Category: JavaScript]]
+
[[Category: Boo]]
+
[[Category: iPhone]]
+
Author: Rozgo
+
  
 
== Description ==
 
== Description ==
  
I created this FingerManager.cs script to handle multiple touches, moves, ends and cancels. Just drop it on only one master object and listen to FingerBegin, FingerMove, FingerEnd and FingerCancel messages on all objects you want to be interactive. The target objects need a collider.  
+
I created this script to handle multiple touches, moves, ends and cancels.
 +
 
 +
== FingerManager.cs ==
  
 
<syntaxhighlight lang="csharp">
 
<syntaxhighlight lang="csharp">
 
// Author: alex@rozgo.com
 
// Author: alex@rozgo.com
// License: enjoy
 
  
using UnityEngine;
 
 
using System.Collections;
 
using System.Collections;
 +
using UnityEngine;
  
public class Finger {
+
public class FingerData
  public iPhoneTouch touch;
+
{
  public bool moved = false;
+
    public Touch Touch;
  public ArrayList colliders = new ArrayList();
+
    public bool Moved = false;
 +
    public ArrayList Colliders = new ArrayList();
 
}
 
}
  
public class FingerManager : MonoBehaviour {
+
public class FingerManager : MonoBehaviour
 
+
{
  public ArrayList fingers = new ArrayList();
+
    public ArrayList Fingers = new ArrayList();
 
+
 
  void Update () {
+
    void FixedUpdate()
      RaycastHit[] hits;
+
    {
      foreach (iPhoneTouch evt in iPhoneInput.touches) {
+
        RaycastHit[] hits;
        if (evt.phase==iPhoneTouchPhase.Began) {
+
 
             Finger finger = new Finger();
+
        foreach (Touch touch in Input.touches)
            finger.touch = evt;
+
        {
            Ray ray = Camera.main.ScreenPointToRay(evt.position);
+
            if (touch.phase == TouchPhase.Began)
            hits = Physics.RaycastAll(ray);
+
             {
            foreach (RaycastHit hit in hits) {
+
                FingerData finger = new FingerData();
              finger.colliders.Add(hit.collider);
+
                finger.Touch = touch;
              GameObject to = hit.collider.gameObject;
+
                Ray ray = Camera.main.ScreenPointToRay(touch.position);
              to.SendMessage("FingerBegin",evt,SendMessageOptions.DontRequireReceiver);
+
                hits = Physics.RaycastAll(ray);
 +
 
 +
                foreach (RaycastHit hit in hits)
 +
                {
 +
                    finger.Colliders.Add(hit.collider);
 +
                    GameObject to = hit.collider.gameObject;
 +
                    to.SendMessage("FingerBegin", touch, SendMessageOptions.DontRequireReceiver);
 +
                }
 +
 
 +
                Fingers.Add(finger);
 
             }
 
             }
             fingers.Add(finger);
+
             else if (touch.phase == TouchPhase.Moved)
        }
+
             {
        else if (evt.phase==iPhoneTouchPhase.Moved) {
+
                for (int i = 0; i < Fingers.Count; ++i)
             for (int i=0;i<fingers.Count;++i) {
+
                {
              Finger finger = (Finger)fingers[i];
+
                    FingerData finger = (FingerData)Fingers[i];
              if (finger.touch.fingerId==evt.fingerId) {
+
                    if (finger.Touch.fingerId == touch.fingerId)
                  finger.moved = true;
+
                    {
                  foreach (Collider collider in finger.colliders) {
+
                        finger.Moved = true;
                    if (collider==null) {continue;}
+
                        foreach (Collider collider in finger.Colliders)
                    GameObject to = collider.gameObject;
+
                        {
                    to.SendMessage("FingerMove",evt,SendMessageOptions.DontRequireReceiver);
+
                            if (collider == null)
                  }
+
                                continue;
              }
+
 
 +
                            GameObject to = collider.gameObject;
 +
                            to.SendMessage("FingerMove", touch, SendMessageOptions.DontRequireReceiver);
 +
                        }
 +
                    }
 +
                }
 
             }
 
             }
        }
+
            else if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled)
        else if (evt.phase==iPhoneTouchPhase.Ended || evt.phase==iPhoneTouchPhase.Canceled) {
+
             {
             Ray ray = Camera.main.ScreenPointToRay(evt.position);
+
                Ray ray = Camera.main.ScreenPointToRay(touch.position);
            hits = Physics.RaycastAll(ray);
+
                hits = Physics.RaycastAll(ray);
            for (int i=0;i<fingers.Count;) {
+
                for (int i = 0; i < Fingers.Count;)
              Finger finger = (Finger)fingers[i];
+
                {
              if (finger.touch.fingerId==evt.fingerId) {
+
                    FingerData finger = (FingerData)Fingers[i];
                  foreach (Collider collider in finger.colliders) {
+
                    if (finger.Touch.fingerId == touch.fingerId)
                    if (collider==null) {continue;}
+
                    {
                    bool canceled = true;
+
                        foreach (Collider collider in finger.Colliders)
                    foreach (RaycastHit hit in hits) {
+
                        {
                        if (hit.collider==collider) {
+
                            if (collider == null)
                          canceled = false;
+
                                continue;
                          GameObject to = collider.gameObject;
+
 
                          to.SendMessage("FingerEnd",evt,SendMessageOptions.DontRequireReceiver);
+
                            bool canceled = true;
 +
 
 +
                            foreach (RaycastHit hit in hits)
 +
                            {
 +
                                if (hit.collider == collider)
 +
                                {
 +
                                    canceled = false;
 +
                                    GameObject to = collider.gameObject;
 +
                                    to.SendMessage("FingerEnd", touch, SendMessageOptions.DontRequireReceiver);
 +
                                }
 +
                            }
 +
                            if (canceled)
 +
                            {
 +
                                GameObject to = collider.gameObject;
 +
                                to.SendMessage("FingerCancel", touch, SendMessageOptions.DontRequireReceiver);
 +
                            }
 
                         }
 
                         }
                    }
+
                         Fingers[i] = Fingers[Fingers.Count - 1];
                    if (canceled) {
+
                        Fingers.RemoveAt(Fingers.Count - 1);
                         GameObject to = collider.gameObject;
+
                    }
                        to.SendMessage("FingerCancel",evt,SendMessageOptions.DontRequireReceiver);
+
                    else
                    }
+
                    {
                  }
+
                        ++i;
                  fingers[i] = fingers[fingers.Count-1];
+
                    }
                  fingers.RemoveAt(fingers.Count-1);
+
                }
              }
+
              else {
+
                  ++i;
+
              }
+
 
             }
 
             }
        }
+
        }
      }
+
    }
  }
+
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
== Usage ==
 +
 +
Just drop the script on only one master object and listen to FingerBegin, FingerMove, FingerEnd and FingerCancel messages on all objects you want to be interactive. The target objects need a collider.
  
 
Write message handlers like this, on each of your interactive objects.
 
Write message handlers like this, on each of your interactive objects.
  
 
<syntaxhighlight lang="csharp">
 
<syntaxhighlight lang="csharp">
void FingerBegin (iPhoneTouch evt) {
+
void FingerBegin (Touch event) {}
}
+
  
void FingerMove (iPhoneTouch evt) {
+
void FingerMove (Touch event) {}
}
+
  
void FingerEnd (iPhoneTouch evt) {
+
void FingerEnd (Touch event) {}
}
+
  
void FingerCancel (iPhoneTouch evt) {
+
void FingerCancel (Touch event) {}
}
+
 
</syntaxhighlight>
 
</syntaxhighlight>
 
Note from UnityQA: Wozik
 
 
If you want maximal preciseness, handle touches in FixedUpdate function, not in OnGUI.
 
 
And I can share a little bug, we're fixing now - after 250-300 continuous (both multiple and single) touches you may see 1-2 more TouchEnded states then TouchStarted. Closer to 400 touches, delta may reach 5-6 touches.
 

Revision as of 00:29, 19 October 2020


Description

I created this script to handle multiple touches, moves, ends and cancels.

FingerManager.cs

// Author: alex@rozgo.com
 
using System.Collections;
using UnityEngine;
 
public class FingerData
{
    public Touch Touch;
    public bool Moved = false;
    public ArrayList Colliders = new ArrayList();
}
 
public class FingerManager : MonoBehaviour
{
    public ArrayList Fingers = new ArrayList();
 
    void FixedUpdate()
    {
        RaycastHit[] hits;
 
        foreach (Touch touch in Input.touches)
        {
            if (touch.phase == TouchPhase.Began)
            {
                FingerData finger = new FingerData();
                finger.Touch = touch;
                Ray ray = Camera.main.ScreenPointToRay(touch.position);
                hits = Physics.RaycastAll(ray);
 
                foreach (RaycastHit hit in hits)
                {
                    finger.Colliders.Add(hit.collider);
                    GameObject to = hit.collider.gameObject;
                    to.SendMessage("FingerBegin", touch, SendMessageOptions.DontRequireReceiver);
                }
 
                Fingers.Add(finger);
            }
            else if (touch.phase == TouchPhase.Moved)
            {
                for (int i = 0; i < Fingers.Count; ++i)
                {
                    FingerData finger = (FingerData)Fingers[i];
                    if (finger.Touch.fingerId == touch.fingerId)
                    {
                        finger.Moved = true;
                        foreach (Collider collider in finger.Colliders)
                        {
                            if (collider == null)
                                continue;
 
                            GameObject to = collider.gameObject;
                            to.SendMessage("FingerMove", touch, SendMessageOptions.DontRequireReceiver);
                        }
                    }
                }
            }
            else if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled)
            {
                Ray ray = Camera.main.ScreenPointToRay(touch.position);
                hits = Physics.RaycastAll(ray);
                for (int i = 0; i < Fingers.Count;)
                {
                    FingerData finger = (FingerData)Fingers[i];
                    if (finger.Touch.fingerId == touch.fingerId)
                    {
                        foreach (Collider collider in finger.Colliders)
                        {
                            if (collider == null)
                                continue;
 
                            bool canceled = true;
 
                            foreach (RaycastHit hit in hits)
                            {
                                if (hit.collider == collider)
                                {
                                    canceled = false;
                                    GameObject to = collider.gameObject;
                                    to.SendMessage("FingerEnd", touch, SendMessageOptions.DontRequireReceiver);
                                }
                            }
                            if (canceled)
                            {
                                GameObject to = collider.gameObject;
                                to.SendMessage("FingerCancel", touch, SendMessageOptions.DontRequireReceiver);
                            }
                        }
                        Fingers[i] = Fingers[Fingers.Count - 1];
                        Fingers.RemoveAt(Fingers.Count - 1);
                    }
                    else
                    {
                        ++i;
                    }
                }
            }
        }
    }
}

Usage

Just drop the script on only one master object and listen to FingerBegin, FingerMove, FingerEnd and FingerCancel messages on all objects you want to be interactive. The target objects need a collider.

Write message handlers like this, on each of your interactive objects.

	void FingerBegin (Touch event) {}
 
	void FingerMove (Touch event) {}
 
	void FingerEnd (Touch event) {}
 
	void FingerCancel (Touch event) {}
Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox