最近项目需求是增加双摇杆,类似王者荣耀中的左摇杆控制角色移动,右摇杆控制技能方向。
项目中没有使用EasyTouch,FingerGestures等插件,是纯代码实现的双摇杆
往常我们在PC中获取点击位置是用Input.mousePosition;而在移动端要获取多点触控,需用到Input.GetTouch(),如果对该方法不了解的,请自行查询。
本次教程实现原理:将屏幕划分左右区域,对原来单纯的获取手指位置,改为获取左右区域中的手指位置。
双摇杆中用到的点击位置,就可以使用
1 |
GetPosition(TouchDirType.Left); |
1 |
GetPosition(TouchDirType.Right); |
下面脚本是解决双摇杆冲突的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
using UnityEngine; using System.Collections; using System.Collections.Generic; using System; public enum TouchDirType { Empty, Left, Right } public class TouchManager : MonoBehaviour { private static TouchManager instance; public static TouchManager Instance { get { return instance; } } float halfWith; static Dictionary<TouchDirType, Vector2> dirTypeTouch; Dictionary<int, TouchDirType> touchIndexType; public Action<TouchDirType> onTouchBegan; // 手指按下时 事件 public Action<TouchDirType> onTouchMoved; // 手指按住时 事件 public Action<TouchDirType> onTouchEnded; // 手指松开时 事件 void Awake() { if (instance == null) instance = this; else Destroy(this); } // Use this for initialization void Start() { halfWith = Screen.width * 0.5f; dirTypeTouch = new Dictionary<TouchDirType, Vector2>(); dirTypeTouch.Add(TouchDirType.Left, Vector2.zero); dirTypeTouch.Add(TouchDirType.Right, Vector2.zero); touchIndexType = new Dictionary<int, TouchDirType>(); } void LateUpdate() { for (int i = 0, length = Input.touchCount > 2 ? 2 : Input.touchCount; i < length; i++) { Touch touch = Input.GetTouch(i); if (touch.phase == TouchPhase.Began) { if (touch.position.x < halfWith) { if (touchIndexType.ContainsKey(touch.fingerId)) { touchIndexType[touch.fingerId] = TouchDirType.Left; } else { touchIndexType.Add(touch.fingerId, TouchDirType.Left); } } else { if (touchIndexType.ContainsKey(touch.fingerId)) { touchIndexType[touch.fingerId] = TouchDirType.Right; } else { touchIndexType.Add(touch.fingerId, TouchDirType.Right); } } dirTypeTouch[touchIndexType[touch.fingerId]] = touch.position; if (onTouchBegan != null) onTouchBegan(touchIndexType[touch.fingerId]); } else if (touch.phase == TouchPhase.Moved) { if (touchIndexType.ContainsKey(touch.fingerId)) { dirTypeTouch[touchIndexType[touch.fingerId]] = touch.position; if (onTouchMoved != null) onTouchMoved(touchIndexType[touch.fingerId]); } } else if (touch.phase == TouchPhase.Ended) { if (touchIndexType.ContainsKey(touch.fingerId)) { if (onTouchEnded != null) onTouchEnded(touchIndexType[touch.fingerId]); dirTypeTouch[touchIndexType[touch.fingerId]] = Vector2.zero; touchIndexType.Remove(touch.fingerId); } } } } /// <summary> /// 通过方向获取输入的坐标 /// </summary> /// <param name="dirType"></param> /// <returns></returns> public static Vector2 GetPosition(TouchDirType dirType) { #if UNITY_EDITOR return Input.mousePosition; #elif UNITY_ANDROID || UNITY_IPHONE return dirTypeTouch[dirType]; #endif } public static string leftOffset; public static string rightOffset; void OnGUI() { GUIStyle bb = new GUIStyle(); bb.normal.background = null; bb.normal.textColor = new Color(1, 0, 0); bb.fontSize = 40; GUI.Label(new Rect(0, 0, 500, 50), "LeftPosition: " + GetPosition(TouchDirType.Left), bb); GUI.Label(new Rect(0, 80, 500, 50), "RightPosition: " + GetPosition(TouchDirType.Right), bb); GUI.Label(new Rect(0, 160, 500, 50), "LeftOffset: " + leftOffset, bb); GUI.Label(new Rect(0, 240, 500, 50), "RightOffset: " + rightOffset, bb); } } |
下面脚本是实现双摇杆的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
using UnityEngine; using System.Collections; public class Joystick : MonoBehaviour { public TouchDirType touchDirType; bool isPress = false; bool touchActionActive = false; float h, v; public float bigCircleRadius = 100; Transform bigCircleTrans; Transform smallCircleTrans; Vector2 bigCircleStartWorldPos = Vector2.zero; Vector2 smallCircleStartLocalPos = Vector2.zero; Vector2 startPressPos; // 技能摇杆按下时的初始位置 即第一帧位置 private Vector2 offset; // 摇杆的偏移量 -1到1 public Vector2 GetOffset() { return new Vector2(h, v); } void Start() { #if UNITY_ANDROID || UNITY_IPHONE TouchManager.Instance.onTouchBegan += OnTouchBegan; #endif bigCircleTrans = transform; smallCircleTrans = transform.GetChild(0); smallCircleStartLocalPos = smallCircleTrans.localPosition; } void Destroy() { #if UNITY_ANDROID || UNITY_IPHONE TouchManager.Instance.onTouchBegan -= OnTouchBegan; #endif } void Update() { if (isPress) { PressIsTrue(); } switch (touchDirType) { case TouchDirType.Empty: break; case TouchDirType.Left: TouchManager.leftOffset = GetOffset().ToString(); break; case TouchDirType.Right: TouchManager.rightOffset = GetOffset().ToString(); break; default: break; } } public void OnPointDown() { #if UNITY_EDITOR this.isPress = true; startPressPos = TouchManager.GetPosition(touchDirType); #endif touchActionActive = true; } public void OnPointUp() { this.isPress = false; smallCircleTrans.localPosition = smallCircleStartLocalPos; touchActionActive = false; // 鼠标抬起时 将 h,v归零 h = 0; v = 0; } #region 手机端使用 public void OnTouchBegan(TouchDirType dirType) { if (dirType != touchDirType || touchActionActive == false ) return; isPress = true; startPressPos = TouchManager.GetPosition(touchDirType); } #endregion // 按下时 触发此方法 void PressIsTrue() { // UICamera.lastTouchPosition 为当前鼠标按下时的坐标(Vector2类型) if (bigCircleStartWorldPos == Vector2.zero) { bigCircleStartWorldPos = Camera.main.WorldToScreenPoint(bigCircleTrans.position); } Vector2 touchPos = TouchManager.GetPosition(touchDirType) - bigCircleStartWorldPos; // 当鼠标拖动的位置与中心位置大于bigCircleRadius时,则固定按钮位置不会超过bigCircleRadius。 bigCircleRadius为背景图片半径长度 if (Vector2.Distance(touchPos, Vector2.zero) > bigCircleRadius) { // 按钮位置为 鼠标方向单位向量 * bigCircleRadius smallCircleTrans.localPosition = touchPos.normalized * bigCircleRadius; } else { // 按钮位置为鼠标位置 smallCircleTrans.localPosition = touchPos; } // 按钮位置x轴 / 半径 的值为0-1的横向偏移量 h = smallCircleTrans.localPosition.x / bigCircleRadius; // 按钮位置y轴 / 半径 的值为0-1的纵向偏移量 v = smallCircleTrans.localPosition.y / bigCircleRadius; } } |
项目使用版本:Unity5.3.4 GitHub下载地址:
https://github.com/654306663/TwoJoystick
- 本文固定链接: http://www.u3d8.com/?p=1174
- 转载请注明: 网虫虫 在 u3d8.com 发表过