都是坑啊,最先写的时候改变的全都是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;
这种方式获得。
原文链接: