摇杆
using System; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; namespace AscensionGame.UI { public class MyJoystick : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler { [Header("摇杆类型")] public EJoystickType EJoystickType = EJoystickType.Fixed; public RectTransform BgRect; public RectTransform HandleRect; public Camera Camera; public Button Btn; private RectTransform mBaseRect; private Canvas mCanvas; public float MoveThreshold; private float deadZone = 0; public float DeadZone { get { return deadZone; } set { deadZone = Mathf.Abs(value); } } public Vector2 input = Vector2.zero; private Vector2 center = new Vector2(0.5f, 0.5f); private Vector2 fixedPosition = Vector2.zero; public GameObject CubeObj; public float MoveSpeed = 8f; private Vector3 StartVec3; protected virtual void Start() { mBaseRect = GetComponent<RectTransform>(); mCanvas = GetComponentInParent<Canvas>(); fixedPosition = BgRect.anchoredPosition; InitData(); Btn.onClick.AddListener(OnClickBtn); } private void SetMode() { if (this.EJoystickType == EJoystickType.Fixed) { BgRect.anchoredPosition = fixedPosition; BgRect.gameObject.SetActive(true); } else { BgRect.gameObject.SetActive(false); } } public void OnPointerDown(PointerEventData eventData) { if (eventData.pointerEnter != null) { Debug.Log($"OnPointerDown{eventData.pointerEnter.name}"); } else { Debug.Log($"OnPointerDown null"); } if (this.EJoystickType != EJoystickType.Fixed) { BgRect.anchoredPosition = ScreenPointToAnchoredPosition(eventData.position); BgRect.gameObject.SetActive(true); } } public void OnDrag(PointerEventData eventData) { if (eventData.pointerEnter != null) { Debug.Log($"OnDrag:{eventData.pointerEnter.name}"); } else { Debug.Log($"OnDrag:null"); } Vector2 position = Camera.WorldToScreenPoint(BgRect.position);//将ui坐标中的background映射到屏幕中的实际坐标 Vector2 radius = (BgRect.sizeDelta - HandleRect.sizeDelta) / 2; input = (eventData.position - position) / (radius * mCanvas.scaleFactor);//将屏幕中的触点和background的距离映射到ui空间下实际的距离 HandleInput(input.magnitude, input.normalized, radius); //对输入进行限制 HandleRect.anchoredPosition = input * radius ; //实时计算handle的位置 } private void Update() { CubeObj.transform.position += new Vector3(input.x, 0f, input.y) * Time.deltaTime * MoveSpeed; } public void OnPointerUp(PointerEventData eventData) { if (eventData.pointerEnter != null) Debug.Log($"OnPointerUp{eventData.pointerEnter.name}"); else { Debug.Log($"OnPointerUp null"); } if (this.EJoystickType != EJoystickType.Fixed) BgRect.gameObject.SetActive(false); input = Vector2.zero; HandleRect.anchoredPosition = Vector2.zero; } public void HandleInput(float magnitude, Vector2 normalised, Vector2 radius) { if (this.EJoystickType == EJoystickType.Dynamic && magnitude > MoveThreshold) { Vector2 difference = normalised * (magnitude - MoveThreshold) * radius; BgRect.anchoredPosition += difference; } if (magnitude > deadZone) { if (magnitude > 1) input = normalised; } else input = Vector2.zero; } private Vector2 ScreenPointToAnchoredPosition(Vector2 screenPosition) { Vector2 localPoint = Vector2.zero; RectTransformUtility.ScreenPointToLocalPointInRectangle(mBaseRect, screenPosition, Camera, out localPoint); return localPoint; } private void OnClickBtn() { switch (EJoystickType) { case EJoystickType.Fixed: EJoystickType = EJoystickType.Floating; break; case EJoystickType.Floating: EJoystickType = EJoystickType.Fixed; break; default: EJoystickType = EJoystickType.Fixed; break; } InitData(); } private void InitData() { BgRect.pivot = center; HandleRect.anchorMin = center; HandleRect.anchorMax = center; HandleRect.pivot = center; HandleRect.anchoredPosition = Vector2.zero; SetMode(); } } }