- Home /
Android 2D multitouch joystick + buttons
I ran out of ideas about my code. I am trying to make a top-down 2D shooter for a school project and I want to control my character with a on-screen joystick and on-screen action buttons. I tried following the YT tutorials such as these:
Devin Curry's: https://www.youtube.com/watch?v=ZGvkaHHQD7c
Sebastian Lague's: https://www.youtube.com/watch?v=SrCUO46jcxk
...Both of them worked great but both had the same issue:
When I touch the button A, then touch the Joystick B And then, when I release my finger from the first button (A), The Joystick gets stuck and I get a : 
UnityException: Index out of bounds.
Joystick.MoveJoyStick () (at Assets/Joystick.cs:43)
Joystick.OnTouchMoved (Int32 myTouch) (at Assets/Joystick.cs:29)
UnityEngine.GameObject:SendMessage(String, Object, SendMessageOptions)
TouchInput:Update() (at Assets/Scripts/TouchInput.cs:44) 
Let me give you my code:
(TouchInput.cs) - placed on main camera, used for touch management, basicly Lague's code with a 2D raycast tweak
 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 
 
 public class TouchInput : MonoBehaviour {
 
     public LayerMask touchInputMask;
 
     private List<GameObject> touchList = new List<GameObject>();
     private GameObject[] touchesOld;
 
     private RaycastHit2D hit;
 
     public static int currentTouch = 0;
 
 
     void Update () {
         if(Input.touchCount > 0) {
             touchesOld = new GameObject[touchList.Count];
             touchList.CopyTo(touchesOld);
             touchList.Clear();
 
             foreach (Touch touch in Input.touches) {
                 hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(touch.position), Vector2.zero, touchInputMask);
                 if(hit.collider != null) {
                     
                     currentTouch = touch.fingerId;
 
                     oldTouch = currentTouch;
                     GameObject recipient = hit.transform.gameObject;
                     touchList.Add(recipient);
 
                     if(touch.phase == TouchPhase.Began) {
                         recipient.SendMessage("OnTouchBegan",currentTouch,SendMessageOptions.DontRequireReceiver);
                     }
                     if(touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Stationary) {
                         recipient.SendMessage("OnTouchMoved",currentTouch,SendMessageOptions.DontRequireReceiver);
                     }
                     if(touch.phase == TouchPhase.Ended) {
                         recipient.SendMessage("OnTouchEnded",currentTouch,SendMessageOptions.DontRequireReceiver);
                     }
                     if(touch.phase == TouchPhase.Canceled) {
                         recipient.SendMessage("OnTouchCanceled",currentTouch,SendMessageOptions.DontRequireReceiver);
                     }
                 }
             }
             foreach(GameObject i in touchesOld) {
                 if(!touchList.Contains(i)) {
                     i.SendMessage("OnTouchEnded",currentTouch,SendMessageOptions.DontRequireReceiver);
                 }
             }
         }
     }
 }
(Joystick.cs) - placed on empty game object that has a 2d collider, The Stick is a children of this game object
 using UnityEngine;
 using System.Collections;
 
 public class Joystick : MonoBehaviour {
 
     private Vector2 touchPos;
     private Vector2 snapPos; //joysticks original position
     [HideInInspector]
     public Vector2 dragDelta;
     public float maxdragDelta = 2f;
     public GameObject _stickGameObject;
     private Transform _stickTransform;
 
     private int Touch_id;
 
     void Start() {
         _stickTransform = _stickGameObject.transform;
         _stickGameObject.renderer.enabled = false;
         snapPos = transform.position;
     }
     
     void OnTouchBegan(int myTouch) {
         _stickGameObject.renderer.enabled = true;
 
         Touch_id = myTouch;
     }
     
     void OnTouchMoved(int myTouch) {
         _stickTransform.position = MoveJoyStick();
     }
     
     void OnTouchEnded(int myTouch) {
         _stickGameObject.renderer.enabled = false;
 
     }
     
     void OnTouchCanceled(int myTouch) {
         _stickTransform.position = MoveJoyStick();
     }
 
     Vector3 MoveJoyStick() {
         
         touchPos = Camera.main.ScreenToWorldPoint(Input.GetTouch(Touch_id).position);
         
         Vector2 moveDir = new Vector3 (touchPos.x - snapPos.x, 
                                        touchPos.y - snapPos.y);
         
         if(moveDir.sqrMagnitude > maxdragDelta * maxdragDelta) {
             moveDir = Vector2.ClampMagnitude(moveDir, maxdragDelta);
         }
         moveDir += snapPos;
 
         return moveDir;
     }
 }
(Button.cs) - just a debug, when you touch it it switches color
 using UnityEngine;
 using System.Collections;
 
 public class Button : MonoBehaviour {
 
     public Color defaulColor;
     public Color selectedColor;
     private Material mat;
 
 
     void Start() {
         mat = renderer.material;
     }
 
     void OnTouchBegan(int myTouch) {
         mat.color = selectedColor;
     }
 
     void OnTouchMoved(int myTouch) {
         mat.color = selectedColor;
     }
 
     void OnTouchEnded(int myTouch) {
         mat.color = defaulColor;
     }
 
     void OnTouchCanceled(int myTouch) {
         mat.color = defaulColor;
     }
 }
PS. Sorry for excessive space use, but I really don't get the idea behind this problem. Just wanted you guys to have a broader look at the code.
Your answer
 
 
             Follow this Question
Related Questions
How to stop second finger from manipulating position of gui joystick 1 Answer
Two or more touchs at same time? 0 Answers
Android: After the third touch all touches get cancelled 1 Answer
Prime 31 Touch Kit detecting if touch hit gui element 1 Answer
Issues with using multitouch and event trigger on 2 joysticks 1 Answer
 koobas.hobune.stream
koobas.hobune.stream 
                       
                
                       
			     
			 
                