using UnityEngine; [RequireComponent(typeof(GUITexture))] public class Joystick : MonoBehaviour { public class Boundary { public Vector2 min = Vector2.zero; public Vector2 max = Vector2.zero; } private static Joystick[] joysticks; private static bool enumeratedJoysticks; private static float tapTimeDelta = 0.3f; public bool touchPad; public Rect touchZone; public Vector2 deadZone = Vector2.zero; public bool normalize; public Vector2 position; public int tapCount; private int lastFingerId = -1; private float tapTimeWindow; private Vector2 fingerDownPos; private GUITexture gui; private Rect defaultRect; private Boundary guiBoundary = new Boundary(); private Vector2 guiTouchOffset; private Vector2 guiCenter; private void Start() { gui = GetComponent(); defaultRect = gui.pixelInset; defaultRect.x += base.transform.position.x * (float)Screen.width; defaultRect.y += base.transform.position.y * (float)Screen.height; base.transform.position = new Vector3(0f, 0f, base.transform.position.z); if (touchPad) { if (gui.texture != null) { touchZone = defaultRect; } return; } guiTouchOffset.x = defaultRect.width * 0.5f; guiTouchOffset.y = defaultRect.height * 0.5f; guiCenter.x = defaultRect.x + guiTouchOffset.x; guiCenter.y = defaultRect.y + guiTouchOffset.y; guiBoundary.min.x = defaultRect.x - guiTouchOffset.x; guiBoundary.max.x = defaultRect.x + guiTouchOffset.x; guiBoundary.min.y = defaultRect.y - guiTouchOffset.y; guiBoundary.max.y = defaultRect.y + guiTouchOffset.y; } private void Update() { if (!enumeratedJoysticks) { joysticks = Object.FindObjectsOfType(); enumeratedJoysticks = true; } int touchCount = Input.touchCount; if (tapTimeWindow > 0f) { tapTimeWindow -= Time.deltaTime; } else { tapCount = 0; } if (touchCount == 0) { ResetJoystick(); } else { for (int i = 0; i < touchCount; i++) { Touch touch = Input.GetTouch(i); Vector2 vector = touch.position - guiTouchOffset; bool flag = false; if (touchPad) { if (touchZone.Contains(touch.position)) { flag = true; } } else if (gui.HitTest(touch.position)) { flag = true; } if (flag && (lastFingerId == -1 || lastFingerId != touch.fingerId)) { if (touchPad) { gui.color = new Color(gui.color.r, gui.color.g, gui.color.b, 0.15f); lastFingerId = touch.fingerId; fingerDownPos = touch.position; } lastFingerId = touch.fingerId; if (tapTimeWindow > 0f) { tapCount++; } else { tapCount = 1; tapTimeWindow = tapTimeDelta; } Joystick[] array = joysticks; foreach (Joystick joystick in array) { if (joystick != this) { joystick.LatchedFinger(touch.fingerId); } } } if (lastFingerId == touch.fingerId) { if (touch.tapCount > tapCount) { tapCount = touch.tapCount; } if (touchPad) { position.x = Mathf.Clamp((touch.position.x - fingerDownPos.x) / (touchZone.width / 2f), -1f, 1f); position.y = Mathf.Clamp((touch.position.y - fingerDownPos.y) / (touchZone.height / 2f), -1f, 1f); } else { gui.pixelInset = new Rect(Mathf.Clamp(vector.x, guiBoundary.min.x, guiBoundary.max.x), Mathf.Clamp(vector.y, guiBoundary.min.y, guiBoundary.max.y), gui.pixelInset.width, gui.pixelInset.height); } if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled) { ResetJoystick(); } } } } if (!touchPad) { position.x = (gui.pixelInset.x + guiTouchOffset.x - guiCenter.x) / guiTouchOffset.x; position.y = (gui.pixelInset.y + guiTouchOffset.y - guiCenter.y) / guiTouchOffset.y; } float num = Mathf.Abs(position.x); float num2 = Mathf.Abs(position.y); if (num < deadZone.x) { position.x = 0f; } else if (normalize) { position.x = Mathf.Sign(position.x) * (num - deadZone.x) / (1f - deadZone.x); } if (num2 < deadZone.y) { position.y = 0f; } else if (normalize) { position.y = Mathf.Sign(position.y) * (num2 - deadZone.y) / (1f - deadZone.y); } } public void ResetJoystick() { gui.pixelInset = defaultRect; lastFingerId = -1; position = Vector2.zero; fingerDownPos = Vector2.zero; if (touchPad) { gui.color = new Color(gui.color.r, gui.color.g, gui.color.b, 0.025f); } } public void LatchedFinger(int fingerId) { if (lastFingerId == fingerId) { ResetJoystick(); } } public void Disable() { base.gameObject.SetActive(false); enumeratedJoysticks = false; } public bool IsFingerDown() { return lastFingerId != -1; } }