Unity中的屏幕坐标系
获得视口宽高
拖动视口会改变屏幕宽高数值
MousePosition
屏幕坐标系的原点在左下角,MousePosition返回Z为0也就是纵深为0的Vector3
但是如果鼠标超出屏幕范围不会做限制,所以可能出现负数或者大于屏幕宽高的情况,做鼠标拖拽物体时需要注意是否需要跟随超出屏幕
下面这个写法是不对的,获得鼠标的屏幕位置纵深将一直为0,屏幕坐标转世界坐标其实是根据距离摄像机的平面确定的(z轴),所以需要先确定z轴后转世界坐标系
GetMouseWorldPosition = Camera.main.ScreenToWorldPoint(GetMousePosition);
利用射线检测物体转屏幕坐标
不会出现超出屏幕坐标系的情况
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out RaycastHit hit))
{
GetObjectPosition = Camera.main.WorldToScreenPoint(hit.point);
}
获得带纵深的屏幕坐标系,xy值为根据屏幕大小决定,z为距离摄像机的位置与本身的世界坐标系z无关
UI坐标
Canvas的世界坐标z值是距离摄像机的距离,那么子物体的世界坐标z值也是与摄像机的距离
实现拖曳UI
屏幕坐标XY是根据屏幕宽高决定,Z是相对摄像机的距离,将屏幕坐标看成一个个屏幕即可
世界坐标是根据世界原点确定,与屏幕坐标的Z值参考不一样
using UnityEngine;
using UnityEngine.EventSystems;
[RequireComponent(typeof(EventTrigger))]
public class DragUI : MonoBehaviour
{
private EventTrigger m_eventTrigger;
private RectTransform m_rectTransform;
private Vector3 m_targetPosition;
private Vector3 m_offsetPosition;
void Start()
{
m_eventTrigger = GetComponent<EventTrigger>();
m_rectTransform = GetComponent<RectTransform>();
EventTrigger.Entry onDragEntry = new EventTrigger.Entry();
onDragEntry.eventID = EventTriggerType.Drag;
onDragEntry.callback.AddListener((data) => { OnDrag(); });
EventTrigger.Entry enterDragEntry = new EventTrigger.Entry();
enterDragEntry.eventID = EventTriggerType.BeginDrag;
enterDragEntry.callback.AddListener((data) => { EnterDrag(); });
m_eventTrigger.triggers.Add(onDragEntry);
m_eventTrigger.triggers.Add(enterDragEntry);
}
private void EnterDrag()
{
m_offsetPosition = GetScreenMousePosition() - m_rectTransform.transform.position;
}
// 拖拽时移动UI
private void OnDrag()
{
// 屏幕坐标转世界坐标
m_targetPosition = GetScreenMousePosition();
m_rectTransform.transform.position = m_targetPosition - m_offsetPosition;
}
// 获得鼠标世界坐标
private Vector3 GetScreenMousePosition()
{
// 与摄像机的距离
float distanceCamera = m_rectTransform.transform.position.z;
// 鼠标位置(确定了平面的Z)
Vector3 screenMousePos = Input.mousePosition + new Vector3(0f, 0f, distanceCamera);
// 屏幕坐标转世界坐标
Vector3 worldMousePos = Camera.main.ScreenToWorldPoint(screenMousePos);
Debug.Log(worldMousePos);
return worldMousePos;
}
}