# MultiTouch (470996)

**URL:** https://discussions.unity.com/t/multitouch-470996/470996
**Category:** Mobile
**Tags:** Android
**Created:** [March 14, 2012, 11:04pm UTC](https://discussions.unity.com/t/multitouch-470996/470996 "2012-03-14T23:04:53Z")
**Posts on this page:** 14
**Page:** 1

<div class="post-metadata">

### Author: ![itanium](https://avatars.discourse-cdn.com/v4/letter/i/6de8d8/32.png) [@itanium](https://discussions.unity.com/u/itanium)
#### Post date: [March 14, 2012, 11:04pm UTC](https://discussions.unity.com/t/multitouch-470996/470996/1 "2012-03-14T23:04:53Z")

</div>

Hello, I’m having a problem with android Input, if more precisely - multitouch.  
I have two buttons(GuiTextures) and they both need to work at the same time(while holding the first one, pressing the other , By example : Jump while running) : It works, but after I press these buttons together, they get stuck. Before pressing both together I can press them each separately as many times as I want and everything works great, but afterwards they get stuck even separately.

These Buttons have two states : Armed and Normal.

Button script :

```auto
		foreach (Touch touch in Input.touches)
					
        {
            if (HitTest(touch.position))
            {
                if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled)
                {
                    SetButtonTexture(ButtonState.normal);
					monstriks.chspeed(0.2f);
                }
                if (touch.phase == TouchPhase.Began)
                {
					if (message == "UP")
					monstriks.chspeed(1.0f);
					else 
					monstriks.down();
					SetButtonTexture(ButtonState.armed);
                }
                break;
            }
        }

```

And Script of the GameObject, who will react on these buttons :

```auto
public void up ()
	{
		
		transform.Translate(0,0,0.5f);	
		Debug.Log("Up Bitch!");
		
	}
	public void down ()
	{
		
		transform.Translate(0,0,-0.5f);	
		Debug.Log("Down bitch!");
		
	}
	
	public void chspeed (float i)
	{
	speed=i;	
		
	}
	// Update is called once per frame
	void Update () 
	{
	 transform.Translate(0,0,speed*Time.deltaTime);
}

```

How to solve this problem?

---

<div class="post-metadata">

### Author: ![TeotiGraphix\_1](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/teotigraphix_1/32/581795_2.png) [@TeotiGraphix\_1](https://discussions.unity.com/u/TeotiGraphix_1)
#### Post date: [March 14, 2012, 11:14pm UTC](https://discussions.unity.com/t/multitouch-470996/470996/2 "2012-03-14T23:14:29Z")

</div>

Hi,

Your not tracking the fingerID. So when you have two fingers down and release one, both handlers are called for the phase of Ended and Canceled.

You need to keep track of the local finger id at a minimum in the behavior script. Something like;

```auto
private int fingerID;

...

if (touch.phase == TouchPhase.Began) {
    fingerID = touch.fingerID;
}

if (tocuh.fingerID == fingerID) {
   // you phase logic here
}

if (touch.phase == TouchPhase.End || touch.phase == TouchPhase.Canceled) {
    fingerID = -1;
}

```

If I am not mistaken, the hitTest() will always return true if you are letting up on the buttons since you over them. It’s a test you use when your in the Begin phase.

The above is by far just pseudo code. Hopefully you get the idea.

Mike

---

<div class="post-metadata">

### Author: ![itanium](https://avatars.discourse-cdn.com/v4/letter/i/6de8d8/32.png) [@itanium](https://discussions.unity.com/u/itanium)
#### Post date: [March 14, 2012, 11:29pm UTC](https://discussions.unity.com/t/multitouch-470996/470996/3 "2012-03-14T23:29:51Z")

</div>

Well, thanks for the quick answer, but will this aproach allow me to press these buttons separately too?

---

<div class="post-metadata">

### Author: ![TeotiGraphix\_1](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/teotigraphix_1/32/581795_2.png) [@TeotiGraphix\_1](https://discussions.unity.com/u/TeotiGraphix_1)
#### Post date: [March 14, 2012, 11:39pm UTC](https://discussions.unity.com/t/multitouch-470996/470996/4 "2012-03-14T23:39:45Z")

</div>

Hi,

Yes, but it’s a bit complicated to show you a full working example. So I might have just confused you more. There is an example on the wiki called FingerManager. This deals with the fingerID, I have used it with great success. Also have gotten some new implementation ideas form it.

See; [http://unifycommunity.com/wiki/index.php?title=FingerManager](http://unifycommunity.com/wiki/index.php?title=FingerManager)

This should help you get up and running quickly.

Mike

---

<div class="post-metadata">

### Author: ![itanium](https://avatars.discourse-cdn.com/v4/letter/i/6de8d8/32.png) [@itanium](https://discussions.unity.com/u/itanium)
#### Post date: [March 15, 2012, 12:15am UTC](https://discussions.unity.com/t/multitouch-470996/470996/5 "2012-03-15T00:15:56Z")

</div>

If I’m not mistaken then, if I will use this approach, then I will have to create for each button a separated script?

> [@](#):
>
> Write message handlers like this, on each of your interactive objects.

I converted that for Android devices and got so far :

```auto
public class Finger 
{
   public Touch touch;
}
	
public ArrayList fingers = new ArrayList();	
   
void Update () 
{
    foreach (Touch evt in Input.touches)
	{
        if (evt.phase==TouchPhase.Began) {
            Finger finger = new Finger();
            finger.touch = evt;
	        fingers.Add(finger);
			}
		else if (evt.phase==TouchPhase.Ended || evt.phase==TouchPhase.Canceled)
		{
        	for (int i=0;i<fingers.Count;) 
			{
	               Finger finger = (Finger)fingers[i];
	               if (finger.touch.fingerId==evt.fingerId) {
	
	               fingers[i] = fingers[fingers.Count-1];
	               fingers.RemoveAt(fingers.Count-1);
				   }
	               else
				   {
	                ++i;
	               }
              }
          }
      }
}

```

Don’t have any idea where to put function calls.``

---

<div class="post-metadata">

### Author: ![TeotiGraphix\_1](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/teotigraphix_1/32/581795_2.png) [@TeotiGraphix\_1](https://discussions.unity.com/u/TeotiGraphix_1)
#### Post date: [March 15, 2012, 9:39am UTC](https://discussions.unity.com/t/multitouch-470996/470996/6 "2012-03-15T09:39:22Z")

</div>

> [@](#):
>
> If I’m not mistaken then, if I will use this approach, then I will have to create for each button a separated script?

For the heck of it you should try and actually use the FingerManager. Add the FingerManager into your Scripts folder. Drop on instance of the FingerManager on a game object like that Camera or an empty GameObject in the scene.

Then in your gui prefab button or wherever you are using the above script implement;

```auto
MyButtonBehavior : MonoBehavior
{
    void FingerBegin (iPhoneTouch evt) {
    }

    void FingerMove (iPhoneTouch evt) {
    }

    void FingerEnd (iPhoneTouch evt) {
    }

    void FingerCancel (iPhoneTouch evt) {
    }
}

```

You should be all set after trying the above.

Mike

---

<div class="post-metadata">

### Author: ![TeotiGraphix\_1](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/teotigraphix_1/32/581795_2.png) [@TeotiGraphix\_1](https://discussions.unity.com/u/TeotiGraphix_1)
#### Post date: [March 15, 2012, 9:41am UTC](https://discussions.unity.com/t/multitouch-470996/470996/7 "2012-03-15T09:41:28Z")

</div>

> [@](#):
>
> I would like to know the differences between a touchscreen and a multitouch screen

They are basically the same thing, the touchscreen is the noun and multitouch is the verb. A touch screen is touched multiple times at the same time.

Multitouch describes handling simultanious touches unlike single mouse events.

Mike

---

<div class="post-metadata">

### Author: ![itanium](https://avatars.discourse-cdn.com/v4/letter/i/6de8d8/32.png) [@itanium](https://discussions.unity.com/u/itanium)
#### Post date: [March 17, 2012, 5:08pm UTC](https://discussions.unity.com/t/multitouch-470996/470996/8 "2012-03-17T17:08:19Z")

</div>

Well, tried several ways and none of them worked normally.  
Only way that worked with this FingerManager was :  
added FingerManager script to camera.

Made a public variable :  
public Component cam;

Then in that manager : `cam.SendMessage("Finger[B]Begin/End/Cancel[/B]",evt,SendMessageOptions.DontRequireReceiver);`

In inspector changed cam object to my button.

And that button has script GuiButton :

```auto
void Finger[B]Begin/End/Cancel[/B] (Touch evt)
	{
                 if(HitTest(evt.position))
                       {
                         SetButtonTexture(ButtonState.normal/armed);
                       }
              }

```

And what I get, was one kinda working button : I can press It, but sometimes it got stuck down(I press on it, buttons texture change, I put my finger of from screen and button still has the same texture. After few touches it goes normal again etc.

---

<div class="post-metadata">

### Author: ![TeotiGraphix\_1](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/teotigraphix_1/32/581795_2.png) [@TeotiGraphix\_1](https://discussions.unity.com/u/TeotiGraphix_1)
#### Post date: [March 17, 2012, 8:54pm UTC](https://discussions.unity.com/t/multitouch-470996/470996/9 "2012-03-17T20:54:33Z")

</div>

I think I know what the issue is. I actually looked at the FingerManager code again yesterday and realized that it is looking at Collider instances.

This means that I wasted your time, sorry about that. The only reason I noticed is because I wanted to track GUITextures as well. I think I’m going to see if I can update that script to handle both use cases.

I will post back here with my results.

Mike

---

<div class="post-metadata">

### Author: ![itanium](https://avatars.discourse-cdn.com/v4/letter/i/6de8d8/32.png) [@itanium](https://discussions.unity.com/u/itanium)
#### Post date: [March 19, 2012, 9:08am UTC](https://discussions.unity.com/t/multitouch-470996/470996/10 "2012-03-19T09:08:10Z")

</div>

🙂  
Well, be waiting for your reply. Of course, will try to get to the answer myself.

---

<div class="post-metadata">

### Author: ![TeotiGraphix\_1](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/teotigraphix_1/32/581795_2.png) [@TeotiGraphix\_1](https://discussions.unity.com/u/TeotiGraphix_1)
#### Post date: [March 19, 2012, 9:57am UTC](https://discussions.unity.com/t/multitouch-470996/470996/11 "2012-03-19T09:57:32Z")

</div>

Hi,

I actually did get this working. I will post the updated code today, just making sure it works correctly. To others; I know there are many toolkits and such out there that do some of this stuff, but if you are just looking to manag fingers, the FingerManager class updated to work with GUITextures/Colliders works pretty good.

If it works for Itanium, I will put an updated version under the original version on the wiki.

Mike

---

<div class="post-metadata">

### Author: ![itanium](https://avatars.discourse-cdn.com/v4/letter/i/6de8d8/32.png) [@itanium](https://discussions.unity.com/u/itanium)
#### Post date: [March 19, 2012, 11:14pm UTC](https://discussions.unity.com/t/multitouch-470996/470996/12 "2012-03-19T23:14:46Z")

</div>

Well, I looked one more time through this topic.  
And I made something similar to your first answer.

```auto
int fingerID=-1;	
       foreach (Touch touch in Input.touches)
        {
            if (myGUITexture.HitTest(touch.position))  
			{
			    if (fingerID == -1)
				{
					if (touch.phase == TouchPhase.Began)
	                {           
						 SetButtonTexture(ButtonState.armed);
						 fingerID=touch.fingerId;
					}
				}
				
				if (touch.fingerId != fingerID)
				{
					SetButtonTexture(ButtonState.armed);
					fingerID=touch.fingerId;
				}
				
				
			    if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled)
                 {
                    SetButtonTexture(ButtonState.normal);
					fingerID=-1;
                 }
			}
            }

```

It still can catch only both(for both fingers) end/cancel at the same time, not separately.  
And I couldn’t find anywhere where I could link these two finger finger ID.

I even tried making two touch end/cancel phase conditionals, two fingerID variables and adding a touch.fingerId=fingerID1/2 to these phases and nothing.

---

<div class="post-metadata">

### Author: ![TeotiGraphix\_1](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/teotigraphix_1/32/581795_2.png) [@TeotiGraphix\_1](https://discussions.unity.com/u/TeotiGraphix_1)
#### Post date: [March 20, 2012, 10:39am UTC](https://discussions.unity.com/t/multitouch-470996/470996/13 "2012-03-20T10:39:17Z")

</div>

@Itanium Sorry about not getting that code up yesteray, things got in the way. When I get back on my dev computer I will just post the code so you can see if it works for you.

---

<div class="post-metadata">

### Author: ![TeotiGraphix\_1](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/teotigraphix_1/32/581795_2.png) [@TeotiGraphix\_1](https://discussions.unity.com/u/TeotiGraphix_1)
#### Post date: [March 20, 2012, 3:02pm UTC](https://discussions.unity.com/t/multitouch-470996/470996/14 "2012-03-20T15:02:43Z")

</div>

I usually don’t paste code like this in forums of other peoples work but hopefully this could be of some use to others that just want some simple multitouch.

If anybody sees anything wrong, let me know. It is working good for me on Android with GUITexture.

```auto
// Author: alex@rozgo.com
// License: enjoy
// mschmalle@teotigraphix.com : Updated to 3.5 and added GUIElement support

using UnityEngine;
using System.Collections;

public class Finger
{
	public Touch touch;
	public bool moved = false;
	public ArrayList colliders = new ArrayList ();
	public ArrayList elements = new ArrayList ();
}

public class FingerManager : MonoBehaviour
{
	public ArrayList elements = new ArrayList ();
	public ArrayList fingers = new ArrayList ();
	
	public void AddFingerListener (GUIElement element)
	{
		elements.Add (element);
	}
	
	public void RemoveFingerListener (GUIElement element)
	{
		elements.Remove (element);
	}
   
	void Update ()
	{
		RaycastHit[] hits;
		foreach (Touch evt in Input.touches) {
			if (evt.phase == TouchPhase.Began) {
				Finger finger = new Finger ();
				finger.touch = evt;
				Ray ray = Camera.main.ScreenPointToRay (evt.position);
				hits = Physics.RaycastAll (ray);
				
				foreach (RaycastHit hit in hits) {
					finger.colliders.Add (hit.collider);
					GameObject to = hit.collider.gameObject;
					to.SendMessage ("FingerBegin", evt, SendMessageOptions.DontRequireReceiver);
				}
				
				//--------------------------------------------------------------
				foreach (GUITexture element in elements) {
					if (element.HitTest (evt.position)) {
						finger.elements.Add (element);
						GameObject to = element.gameObject;
						to.SendMessage ("FingerBegin", evt, SendMessageOptions.DontRequireReceiver);
					}
				}
				//--------------------------------------------------------------
				
				fingers.Add (finger);
			} else if (evt.phase == TouchPhase.Moved) {
				for (int i=0; i<fingers.Count; ++i) {
					Finger finger = (Finger)fingers [i];
					if (finger.touch.fingerId == evt.fingerId) {
						finger.moved = true;
						foreach (Collider collider in finger.colliders) {
							if (collider == null)
								continue;
							
							GameObject to = collider.gameObject;
							to.SendMessage ("FingerMove", evt, SendMessageOptions.DontRequireReceiver);
						}
						//--------------------------------------------------------------
						foreach (GUITexture element in finger.elements) {
							if (element == null)
								continue;
							
							GameObject to = element.gameObject;
							to.SendMessage ("FingerMove", evt, SendMessageOptions.DontRequireReceiver);
						}
						//--------------------------------------------------------------
					}
				}
			} else if (evt.phase == TouchPhase.Ended || evt.phase == TouchPhase.Canceled) {
				
				Ray ray = Camera.main.ScreenPointToRay (evt.position);
				hits = Physics.RaycastAll (ray);
				for (int i=0; i<fingers.Count;) {
					Finger finger = (Finger)fingers [i];
					if (finger.touch.fingerId == evt.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", evt, SendMessageOptions.DontRequireReceiver);
								}
							}
							if (canceled) {
								GameObject to = collider.gameObject;
								to.SendMessage ("FingerCancel", evt, SendMessageOptions.DontRequireReceiver);
							}
						}
						//--------------------------------------------------------------
						foreach (GUITexture element in finger.elements) {
							if (element == null)
								continue;
							
							bool canceled = true;
							if (element.HitTest (evt.position)) {
								canceled = false;
								GameObject to = element.gameObject;
								to.SendMessage ("FingerEnd", evt, SendMessageOptions.DontRequireReceiver);
							}
							if (canceled) {
								GameObject to = element.gameObject;
								to.SendMessage ("FingerCancel", evt, SendMessageOptions.DontRequireReceiver);
							}
						}
						//--------------------------------------------------------------
						fingers [i] = fingers [fingers.Count - 1];
						fingers.RemoveAt (fingers.Count - 1);
					} else {
						++i;
					}
				}
			}
		}
	}
}

```

Then on any GUITexture you want to listen.

**GUITextureCollider.cs**

```auto
using UnityEngine;

[RequireComponent(typeof(FingerManager))]

public class GUITextureCollider : MonoBehaviour {
	
	void Awake () {
		FingerManager manager = (FingerManager) FindObjectOfType(typeof(FingerManager));
		manager.SendMessage("AddFingerListener", guiTexture, SendMessageOptions.RequireReceiver);
	}
	
	void FingerBegin()
	{
		Debug.Log("FingerBegin");
	}
	
	void FingerMove()
	{
		Debug.Log("FingerMove");
	}
	
	void FingerEnd()
	{
		Debug.Log("FingerEnd");
	}
	
	void FingerCancel()
	{
		Debug.Log("FingerCancel");
	}
}

```

If this is good, then it could be put on the wiki underneath the original I suppose.

Mike
