摇杆

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();
        }
    }
}

 

posted @ 2023-08-31 11:26  色色先生  阅读(39)  评论(0编辑  收藏  举报