- 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