[Unity]自适应,动态变化位置的摇杆的实现。

都是坑啊,最先写的时候改变的全都是UI的position,本来看似都OK的,但是发现改变屏幕分辨率之后,摇杆可拖动范围居然不一样。这就很影响体验了,最后还是耐着性子把原本需要改变position来实现的改成了更改UI元素的anchoredPosition,也就是锚点位置,因为锚点位置是相对的,所以不同分辨率下,相对位置始终不变,即可以自适应了。

话不多说,下面是代码。

代码挺简单的,注释也挺详细,就不多赘述了。

因为是用Fingergesture做的,所以没有继承IDrag那些接口。

因为在做的过程中发现使用那些接口去做Drag事件的话,当动态改变位置的那一瞬间,UI识别不到drag事件,具体原因不详,后来改为了Fingergesture来做。

using System;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class JoystickController : MonoBehaviour
    {

		//摇杆半径
        private float joyRadius;
        [HideInInspector]
        public Vector3 playerMoveDir;
        //摇杆中心
        [SerializeField]
        private RectTransform joyCenter;
        //摇杆外围
        private RectTransform joyRange;

        [Range(0, 1)]
        public float gravitySensitivity = 0.3f;
        //摇杆外围起始位置
        private Vector2 joyRangeBeginPos;
        //摇杆中心起始位置
        private Vector2 joyCenterBeginPos;

        //画布
        private Canvas canvas;
        //UI相机
        private Camera uirootCamera;


        void Start()
        {
			//获取圆的半径
            joyRadius = this.GetComponent<RectTransform>().rect.size.x * 0.5f;
            canvas = GameObject.Find("UIRoot").transform.GetChild(0).GetComponent<Canvas>();
            uirootCamera = GameObject.Find("UIRoot").transform.GetChild(2).GetComponent<Camera>();
            joyRange = this.GetComponent<RectTransform>();
        }


        public void OnBeginDrag()
        {

            Vector2 _posMouse = new Vector2();
			//屏幕坐标和UI坐标的转换
            RectTransformUtility.ScreenPointToLocalPointInRectangle(joyRange, Input.mousePosition, uirootCamera, out _posMouse);
			//因为我的摇杆锚点在左下,所以做一个差值计算
            joyRangeBeginPos = new Vector2(_posMouse.x - joyRange.sizeDelta.x * 0.5f, _posMouse.y - joyRange.sizeDelta.x * 0.5f);
			//将摇杆的中心位置设置为鼠标点击的位置,即动态变化摇杆位置
            joyRange.anchoredPosition = joyRangeBeginPos;
			//记录下当前摇杆拖动的位置
            joyCenterBeginPos = joyCenter.anchoredPosition;

        }

        public void OnDrag()
        {
		
            Vector2 _posMouse = new Vector2();
            RectTransformUtility.ScreenPointToLocalPointInRectangle(joyRange, Input.mousePosition, uirootCamera, out _posMouse);
            _posMouse = new Vector2(_posMouse.x - joyRange.sizeDelta.x * 0.5f, _posMouse.y - joyRange.sizeDelta.x * 0.5f);
            //拖拽方向
			Vector2 dragDir = _posMouse - joyCenterBeginPos;
			//拖拽距离
            float dis = dragDir.magnitude;

            if (dis <= joyRadius)
            {
                joyCenter.anchoredPosition = _posMouse;
            }
            else
            {
                joyCenter.anchoredPosition = dragDir.normalized * joyRadius;
            }
			//玩家移动方向
            playerMoveDir = new Vector3(dragDir.x, dragDir.y, 0);

        }

        public void OnEndDrag()
        {
            joyRange.anchoredPosition = joyCenter.anchoredPosition = Vector2.zero;
        }
  
}

下面是工程截图,以及摇杆锚点轴点示意图:



--------------------------------------------------分割线-----------------------------------------------------


RectTransformUtility.ScreenPointToLocalPointInRectangle

其实这个矩阵变换方法的第一个参数设为UGUI的根canvans的RectTransform就行:

RectTransformUtility.ScreenPointToLocalPointInRectangle(RootCanvas.GetComponent<RectTransform>(), screenPos, UICamera, out tarVec);

tips:

canvans的RectTransform可以以.GetComponent<RectTransform>()的方式获得,目前使用没有什么问题。

但是有文章写道不推荐这么获得RectTransform,如果.GetComponent<RectTransform>()有什么问题的话可以尝试他推荐的:

RootCanvas.transform as RectTransform;

这种方式获得。

原文链接:

点击打开链接


猜你喜欢

转载自blog.csdn.net/qq302756113/article/details/79204152
今日推荐