Contents

实现简单摇杆

Contents
using ProjectBase.EventCenter;
using ProjectBase.UI;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using EventType = ProjectBase.EventCenter.EventType;

namespace UI.JoyStick
{
    public class JoystickPanel : BasePanel
    {
        private Image mJoystickBg;
        private Image mJoystickControl;
        private Image mJoystickPanel;

        /// <summary>
        /// 遥杆初始位置
        /// </summary>
        private Vector2 mInitLocalPos;

        /// <summary>
        /// 摇杆按钮移动的最大位置
        /// </summary>
        private Vector2 mMaxLoaclPos;

        /// <summary>
        /// 鼠标位置在Bg下的局部坐标
        /// </summary>
        private Vector2 mLocalPos;


        /// <summary>
        /// 鼠标位置在面板下的局部坐标
        /// </summary>
        private Vector2 mBgLocalPos;


        void Start()
        {
            GetChildControl<Image>();
            mJoystickBg = GetControl<Image>("JoystickBg");
            mJoystickControl = GetControl<Image>("JoystickControl");
            mJoystickPanel = GetControl<Image>("JoystickPanel");
            mInitLocalPos = mJoystickBg.rectTransform.localPosition;
            //为面板添加自定义事件
            UIMgr.Instance.AddCustomizeEventListener(gameObject, EventTriggerType.PointerDown,
                OnPointerDown);
            UIMgr.Instance.AddCustomizeEventListener(gameObject, EventTriggerType.PointerUp, OnPointerUp);
            UIMgr.Instance.AddCustomizeEventListener(gameObject, EventTriggerType.Drag, OnDrag);
        }

        /// <summary>
        /// 更新位置数据
        /// </summary>
        /// <param name="data"></param>
        private void UpdatePos(BaseEventData data)
        {
            mLocalPos = UIMgr.Instance.ScreenPointToLocalPoint(data as PointerEventData, mJoystickBg.rectTransform);
            mMaxLoaclPos = mLocalPos.normalized * mJoystickBg.rectTransform.rect.width * 0.5f;
            mBgLocalPos =
                UIMgr.Instance.ScreenPointToLocalPoint(data as PointerEventData, mJoystickPanel.rectTransform);
        }

        private void OnPointerDown(BaseEventData data)
        {
            UpdatePos(data);
            if (mLocalPos.sqrMagnitude > mMaxLoaclPos.sqrMagnitude)
            {
                //如果超过最大距离 让摇杆在手指下方
                mJoystickBg.rectTransform.localPosition = mBgLocalPos;
            }
        }

        private void OnPointerUp(BaseEventData data)
        {
            mJoystickControl.transform.localPosition = Vector2.zero;
            mJoystickBg.rectTransform.localPosition = mInitLocalPos;
            //分发摇杆抬起事件
            EventMgr.Instance.EventTrigger(EventType.JoyStickUp, Vector2.zero);
        }

        private void OnDrag(BaseEventData data)
        {
            UpdatePos(data);
            if (mLocalPos.sqrMagnitude > mMaxLoaclPos.sqrMagnitude)
            {
                mJoystickControl.transform.localPosition = mMaxLoaclPos;
                //让摇杆跟着手指
                mJoystickBg.transform.localPosition = mBgLocalPos - mMaxLoaclPos;
            }
            else
            {
                mJoystickControl.transform.localPosition = mLocalPos;
            }
            //分发摇杆拖拽事件
            EventMgr.Instance.EventTrigger(EventType.JoyStickUpdate, mLocalPos.normalized);
        }
    }
}

测试

using ProjectBase.EventCenter;
using ProjectBase.UI;
using UI.JoyStick;
using UnityEngine;
using EventType = ProjectBase.EventCenter.EventType;

public class Move : MonoBehaviour
{
    public float Speed = 20;
    private Vector3 mDir;
    private bool mIsMove;

    void Start()
    {
        UIMgr.Instance.ShowPanel<JoystickPanel>("JoystickPanel",EUiLayer.Top);
        EventMgr.Instance.AddEventListener<Vector2>(EventType.JoyStickUpdate, (data) =>
        {
            mIsMove = true;
            ChangeDir(data);
        });
        EventMgr.Instance.AddEventListener<Vector2>(EventType.JoyStickUp, (data) => { mIsMove = false; });
    }


    void Update()
    {
        if (mIsMove)
        {
            // transform.LookAt(transform.position + mDir);
            transform.rotation = Quaternion.LookRotation(mDir);
            // transform.Translate(Vector3.forward*Time.deltaTime*Speed,Space.Self);//通过自身的坐标向前移动
            transform.Translate(mDir*Time.deltaTime*Speed,Space.World);//通过世界坐标
        }
    }

    private void ChangeDir(Vector2 vector2)
    {
        mDir.x = vector2.x;
        mDir.z = vector2.y;
    }
}

使用了前面写的事件中心和UI框架,要注意不同坐标系之间的转换,比较容易弄乱。