- Home /
Unusual multitouch behavior (Android)
Hi, I'm hoping someone can help shed some light on this problem I've been trying to solve over the past couple of days with no luck.
So the idea is that I'm trying to detect multiple touches on an Android device with the purpose being for each touch to move its' own gameobject. The problem I am encountering is that when I have 2 touches, and the 1st touch ends/cancels, the 2nd touch also seems to stop with it, what's weirder is that as soon as I initiate another (originally 1st) touch, the 2nd touch that did not end will suddenly continue to move the gameobject just fine.
This is a rough/simplified representation of the code I have:
public class TrackerHandlerScript : MonoBehaviour {
public static GameObject[] trackerArray = new GameObject[2];
private int _tapCount;
private Object trackerPrefab;
// Use this for initialization
void Start () {
trackerPrefab = Resources.Load("Prefabs/prefab_tracker");
}
// Update is called once per frame
void Update () {
_tapCount = Input.touchCount;
if(_tapCount > 0 ){
for(int i = 0; i < _tapCount; i++){
if(Input.GetTouch(i).phase == TouchPhase.Began){
createTracker(i, Input.GetTouch(i).fingerId);
}
}
}
}
void createTracker(int idx, int id = 0){
if(trackerArray[idx] != null){
Destroy(trackerArray[idx] .gameObject);
}
trackerArray[idx] = Instantiate(trackerPrefab, Vector3.zero, Quaternion.identity) as GameObject;
trackerArray[idx] .GetComponent<TrackerScript>().touch = id;
}
}
The idea here is that I store my 2 gameobjects in an array and only instantiate a tracker into an empty index. This seems to be working as intended.
This is the logic in the gameobject's script that handles the touch:
public class TrackerScript : MonoBehaviour {
public int idx;
public int touch;
Vector3 pos;
void Update () {
for(int i = 0; i < Input.touchCount; i++){
if(Input.GetTouch(i).fingerId == touch){
if(Input.GetTouch(i).phase == TouchPhase.Ended || Input.GetTouch(i).phase == TouchPhase.Canceled){
Destroy(gameObject);
}
}
}
for(int i = 0; i < Input.touchCount; i++){
if(Input.GetTouch(i).fingerId == touch){
pos = Input.GetTouch(i).position;
}
}
_transform.position = Camera.main.ScreenToWorldPoint(pos)
}
}
So no syntax errors or anything (in case I made a typo or left anything out). The idea here is that I use the passed fingerId from the handler to identify the touch and only move the gameobject if it's a match. Releasing the touch will destroy the gameobject thus nullifying the index for the tracker array.
Once again, if anyone has any idea what might be wrong with this code/logic, I'm all ears.
P.S. I am on Unity 4.6.3f for full disclosure.
edit: updated some of the code.
Answer by inihility · Oct 11, 2015 at 10:54 AM
I managed to resolve the issue.
For anyone who's curious, it is mainly with how Unity handles touches, I had to centralize what I did with the touches all in one place in order to maintain the correct touch indexes.
Answer by hexagonius · Oct 10, 2015 at 04:59 PM
the second stops because your for loop iterates only as often as fingers on the screen, leaving touch 2 out after you removed whatever finger. you must not bind the finger id to their initial touch index, but check them all against however many touched you have.
I've already submitted a comment (pending?) that I solved my problem, but this is exactly what I had to do; check touches against the touch count and do stuff there ins$$anonymous$$d of trying to 'bind' a touch to an index.
Answer by s4shrish · Oct 22, 2019 at 07:17 AM
Yeah, just printed a long list of debug.logs to figure out the issue myself. Unity handles touch in a weird manner.
So if put your first finger, say on a blue object, it will have touchIndex (in Input.GetTouch(index)) of "0" and then if you put your second finger, say on an orange obj, it will have a touch index of "1". Now obviously when you lift any of the finger, whether 0 or 1 (blue or orange), the remaining touch will have the index of "0", which is not what I initially expected, but makes sense in an array. Fair enough.
So if the finger you lifted from the screen was your second finger (ie the one on orange obj) and put it back on the screen, it will have once again touch index of "1". But if you lifted your first finger (ie the one on blue obj), and put it back on, you would expect the new finger to have the index of "1", but it will have an index of "0" in the array, and the finger on orange will have index of "1", even tho when it was single touch it had an index of "0", it will be changed. THIS caused my objects swap positions quickly when I lifted my finger from one object. But not if it was second finger that was being lifted. Took me quite some time to figure it out, maybe next time I will use fingerID, or heck make alternate script that uses fingerID. Correct me tho if this is not how it works.
Just putting my encounter with an issue out there if someone had this issue with Unity's touches and didn't know how touches function in multi-touch situation in Unity.
Your answer
Follow this Question
Related Questions
Multitouch loses touch even when finger still on screen. 0 Answers
Touch.Phase Differences ? 2 Answers
Merging touches 0 Answers