自己做了个飞行模拟的小游戏,发布到手机上需要用到摇杆来控制,所以自己写了一个Joystick类,代码如下:
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
| using UnityEngine; using UnityEngine.EventSystems; using System;
public class Joystick : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IDragHandler { public static Joystick instance; [SerializeField] Camera uiCamera; [SerializeField] RectTransform _triggerArea; [SerializeField] RectTransform _joyStickArea; [SerializeField] RectTransform centerTrans; [SerializeField] float sensitivity = 1; [SerializeField] float triggerAreaScale = 1; public Vector2 moveDir { get; private set; } public float moveLen { get; private set; } public bool isDraging { get; private set; } public float Horizontal { get { return moveDir.x * moveLen; } } public float Vertical { get { return moveDir.y * moveLen; } }
Canvas _canvas; Canvas canvas { get { if (_canvas == null) _canvas = transform.GetComponentInParent<Canvas>(); return _canvas; } } Vector3 targetScreenPointPos = Vector3.zero;
float radius = 0f; Vector3 centerScreenPos; float depth { get { return centerScreenPos.z; } } bool hasInit = false;
public Action onJoyStickPointerUp; private void Start() { instance = this;
} void OnEnable() { InitParam(); } void OnDisable() { isDraging = false; targetScreenPointPos = centerScreenPos; centerTrans.localPosition = Vector3.zero; } void InitParam() { if (hasInit) return; hasInit = true; centerScreenPos = uiCamera.WorldToScreenPoint(_joyStickArea.position); Rect rect = RectTransformUtility.PixelAdjustRect(_joyStickArea, canvas); radius = triggerAreaScale * rect.width/2; targetScreenPointPos = centerScreenPos; } public void OnPointerDown(PointerEventData eventData) { InitParam(); Vector2 pointScreenPos = eventData.position;
isDraging = true;
} public void OnDrag(PointerEventData eventData) { if (!isDraging) return; Vector3 pointScreenPos = eventData.position; pointScreenPos.z = depth; Vector3 dir = pointScreenPos - centerScreenPos; float len = dir.magnitude; len = len > radius ? radius : len; dir = len * dir.normalized; targetScreenPointPos = centerScreenPos + dir; }
public void OnPointerUp(PointerEventData eventData) { isDraging = false; targetScreenPointPos = centerScreenPos; onJoyStickPointerUp?.Invoke(); } private void Update() { Vector3 screenPointPos = uiCamera.WorldToScreenPoint(centerTrans.position); if(Vector3.Distance(screenPointPos, targetScreenPointPos)<4) { screenPointPos = targetScreenPointPos; } else { screenPointPos = Vector3.Lerp(screenPointPos, targetScreenPointPos, sensitivity * Time.deltaTime); }
centerTrans.position = uiCamera.ScreenToWorldPoint(screenPointPos); moveDir = screenPointPos - centerScreenPos; moveDir /= radius; moveLen = moveDir.magnitude; moveLen = moveLen > 1 ? 1 : moveLen; } }
|
通过属性器可以获取当前摇杆的状态参数,包括偏移方向以及强度,方向是360度,强度是[0-1]。还有几个SerializeField
面板设置参数,结构如下图: