Camera.ScreenPointToRay用法
var ray = Camera.ScreenPointToRay(screenPos);
1) screenPos需要是左下角为(0, 0), 单位为像素的屏幕坐标。
2) 得到的射线的开始为屏幕坐标在相机near平面上的点, 指向屏幕坐标在far平面上的点
在游戏代码中使用
using UnityEngine; public class TestCameraRay : MonoBehaviour { private void Update() { if (Input.GetMouseButtonDown(0)) { var cam = Camera.main; if (cam) { var screenPos = Input.mousePosition; var ray = cam.ScreenPointToRay(screenPos); var v1 = ray.origin; var v2 = v1 + ray.direction * 60; Debug.Log($"ray: {ray}, {v2}"); Debug.DrawLine(v1, v2, Color.red, 5); screenPos.z = -cam.transform.position.z; //如果用0得到的将是相机的z值 var worldPos = cam.ScreenToWorldPoint(screenPos); //z=camWorldPos.z+screenPos.z, 所以将得到z值在0处的世界坐标 Debug.Log($"screen:{screenPos} -> world:{worldPos}"); Debug.DrawLine(v1, worldPos, Color.blue, 5); } } } }
效果
在编辑器代码中使用,会用到 HandleUtility.GUIPointToWorldRay(mousePos);
实际也是调用Camera.ScreenPointToRay
public class TestCameraRay : MonoBehaviour { public Camera m_SceneCam; private void OnDrawGizmos() { var curEvent = Event.current; if (curEvent.isMouse) { var cam = Camera.current; if (cam) { var sceneCam = SceneView.currentDrawingSceneView.camera; if (cam == sceneCam) Debug.Log($"cam equals"); var ray = HandleUtility.GUIPointToWorldRay(curEvent.mousePosition); var v1 = ray.origin; var v2 = v1 + ray.direction * 999; Debug.Log($"ray: {ray}, {v2}"); Debug.DrawLine(v1, v2, Color.blue, 10); Vector3 screenPos = HandleUtility.GUIPointToScreenPixelCoordinate(curEvent.mousePosition); //转换成像素单位以及左下角(0, 0) screenPos.z = -cam.transform.position.z; var worldPos = cam.ScreenToWorldPoint(screenPos); //z=camWorldPos.z+screenPos.z, 所以将得到z值在0处的世界坐标 Debug.Log($"mousePos:{curEvent.mousePosition} -> screen:{screenPos} -> world:{worldPos}"); //Debug.DrawLine(v1, worldPos, Color.blue, 5); if (m_SceneCam) //把场景相机显示出来, 不然没法看到场景相机 { var tempCamTf = m_SceneCam.transform; tempCamTf.position = camTf.position; tempCamTf.forward = camTf.forward; m_SceneCam.orthographic = cam.orthographic; m_SceneCam.fieldOfView = cam.fieldOfView; m_SceneCam.orthographicSize = cam.orthographicSize; m_SceneCam.nearClipPlane = cam.nearClipPlane; m_SceneCam.farClipPlane = cam.farClipPlane; } } } } }
效果
一些API的用法
游戏代码中使用:
Input.mousePosition: 拿到的是游戏窗口的屏幕坐标, 左下角为(0, 0), 右上角为游戏窗口宽高, 单位为像素
Event.PopEvent(evt).mousePosition: 拿到的是游戏窗口的屏幕坐标, 左上角为(0, 0), , 右上角为游戏窗口宽高, 单位为像素
编辑器代码中使用:
EditorGUIUtility.pixelsPerPoint: win10将显示设置中的缩放设置为125%时, 值为1.25; 设置为100%时, 值为1.0
Event.current.mousePosition: 拿到的是Scene窗口的屏幕坐标, 左上角为(0, 0), 右上角为Scene窗口宽高, 单位为点数, 要转pixel的需乘EditorGUIUtility.pixelsPerPoint
均可使用:
Screen.width, Screen.height: 在游戏代码中拿到的是游戏窗口的大小, 在编辑器代码中拿到的是Scene窗口的大小, 单位为像素
Screen.dpi: win10将显示设置中的缩放设置为125%时, 值为120; 设置为100%时, 值为96
参考
Unity编辑器/运行时屏幕坐标转世界坐标问题 - 哔哩哔哩 (bilibili.com)
Unity SceneView 鼠标转世界坐标 - 【Winco】 - 博客园 (cnblogs.com)