Unity摇杆移动

虚拟摇杆,可以控制人物的的移动,及其旋转,或者是控制技能的释放方向。此篇博客就unity中如何实现利用UI(虚拟摇杆)控制物体的移动和旋转
场景界面【等待完善】
代码如下:

using UnityEngine;
using UnityEngine.EventSystems;
using System;
using UnityEngine.UI;
using GA;
public class RockerCtrl : IPointerDownHandler,IPointerUpHandler,IDragHandler
{
    
    
    [Header("滑动区域")]
    public RectTransform sildeArea;
    [Header("摇杆背景")]
    public RectTransform rockerBg;
    [Header("摇杆点")]
    public RectTransform rockerPoint;
    [Header("摇杆半径")]
    public float radius;

    public RockerCtrl Instance;

    public CanvasScaler canvasScaler;

    /// <summary>
    /// 是否正在摇杆滑动
    /// </summary>
    [NonSerialized]
    public bool isRockering = false;

    /// <summary>
    /// 设置移动方向
    /// </summary>
    private static Action<Vector2> setDir;

    /// <summary>
    /// 开始点击的位置(世界坐标系)
    /// </summary>
    private Vector3 startWorldPos = Vector2.zero;

    /// <summary>
    /// 开始点击的位置(屏幕坐标系)
    /// </summary>
    private Vector2 startEventPos = Vector2.zero;

    /// <summary>
    /// 摇杆默认位置
    /// </summary>
    private Vector2 defaultPos = Vector2.zero;

    protected void Awake()
    {
    
    
        Instance = this;
        //初始化变量
        if (rockerBg.gameObject.activeSelf)
            rockerBg.gameObject.SetActive(false);
    }

    private void Start()
    {
    
    
        canvasScaler = transform.parent.parent.parent.GetComponent<CanvasScaler>();//TODO

        radius *= GetWidthOrHeightAspect();//计算在不同分辨率下的半径
    }

    /// <summary>
    /// 点击事件
    /// </summary>
    public void OnPointerDown(PointerEventData eventData)
    {
    
    
        isRockering = true;
        //在点击点显示摇杆
        //摄像机模式 需要将屏幕坐标转化世界坐标
        Vector3 worldPos;
        bool isOk = RectTransformUtility.ScreenPointToWorldPointInRectangle(sildeArea, eventData.position, eventData.enterEventCamera, out worldPos);//设置摇杆位置
        if (isOk)
        {
    
    
            rockerBg.position = worldPos;
            startEventPos = eventData.position;
            startWorldPos = worldPos;
        }
        rockerBg.gameObject.SetActive(true);//显示摇杆
    }

    /// <summary>
    /// 拖拽事件
    /// </summary>
    public void OnDrag(PointerEventData eventData)
    {
    
    
        Vector3 currentPos;//世界坐标
        bool isOk = RectTransformUtility.ScreenPointToWorldPointInRectangle(sildeArea, eventData.position, eventData.enterEventCamera, out currentPos);
        if (isOk)
        {
    
    
            Vector3 dir = eventData.position - startEventPos;//屏幕坐标系下滑动的向量
            float len = dir.magnitude;//滑动向量的 长度
            if (len > radius)//滑动的位置大于滑动半径 控制point在半径边界 
            {
    
    
                Vector3 clampDir = Vector3.ClampMagnitude(dir, radius);//限制向量的宽度
                rockerPoint.localPosition =  clampDir;
            }
            else
                rockerPoint.position = currentPos;

            if (setDir != null)
                setDir(-dir.normalized);//去反方向 和运动方向保持一致
        }
    }

    /// <summary>
    /// 抬起事件
    /// </summary>
    /// <param name="eventData"></param>
    public void OnPointerUp(PointerEventData eventData)
    {
    
    
        isRockering = false;
        //摇杆归位
        rockerBg.position = defaultPos;
        rockerPoint.position = defaultPos;
        rockerBg.gameObject.SetActive(false);//隐藏摇杆
        if (setDir != null)
            setDir(Vector2.zero);
    }

    /// <summary>
    /// 添加设置移动方向事件
    /// </summary>
    public static void AddSetDirEvent(Action<Vector2> action)
    {
    
    
        if (setDir == null && action != null)
            setDir = action;
    }

    /// <summary>
    /// 移除设置移动方向事件
    /// </summary>
    public static void RemoveSetDirEvent()
    {
    
    
        if (setDir != null)
            setDir = null;
    }

    /// <summary>
    /// 得到相对宽高比
    /// </summary>
    public  float GetWidthOrHeightAspect()
    {
    
    
        float temp = 1.0f;
        float matchWidthOrHeight = canvasScaler.matchWidthOrHeight;
        if (matchWidthOrHeight > 0)//高适配
            temp = Screen.height * 1.0f /Config.Instance.CanvasRealHeight;
        else//宽适配
            temp = Screen.width * 1.0f / Config.Instance.CanvasRealWidth;
        return temp;
    }
}

猜你喜欢

转载自blog.csdn.net/baidu_39447417/article/details/111399299