[Unity踩坑记录] 从屏幕坐标系转换到世界坐标系

问题描述

调试需要,想从摄像机发出一条射向鼠标指向位置的射线,于是写了如下代码:

void Update(){
    
    
	Vector3 mouseScreenPos = Input.mousePosition;
	Vector3 mouseWorldPos = Camera.main.ScreenToWorldPoint(mouseScreenPos);
	Debug.DrawRay (Camera.main.transform.position, mouseWorldPos, red);

运行后发现,不论鼠标指向哪里,射线都是射向同一方向。
随后对鼠标坐标、转换后的鼠标坐标进行打印,发现鼠标坐标正常,但转换后的鼠标坐标全部为(0,1,-10)

问题分析

Camera.main.ScreenToWorldPoint()中进行运算的坐标为Vector3类型,而鼠标屏幕坐标的z为0。当camera设置为perspective时,经过该方法计算得出的坐标会永远是camera的坐标。

总之,使用纯天然的鼠标坐标只会得到一个固定的相机坐标。

The ‘z’ parameter must be the distance in front of the camera. In perspective mode at least, passing 0 will cause ScreenToWorldPoint() to always return the position of the camera.
 
Note the measurement for the ‘z’ parameter is from camera plane to the playing surface plane. It is not the distance between the camera and the object. If the camera is aligned with the axes, then the distance is easy to calculate. If the camera is at an angle (i.e. not axes aligned), then ScreenToWorldPoint() is not the way to go.

解决方案

发射射线只需要方向向量,所以其实只要手动给z改个非零值即可。

但是如果更进一步想,一些需要跟随鼠标位置进行移动的效果,就必须要知道z的具体值。

无法将鼠标坐标直接转换成世界坐标,或者说计算z值过于复杂,那就反过来,把什么东西转换成屏幕坐标,再把它的z值赋给鼠标坐标。

以下代码也适用于想通过鼠标来移动一些物体(如鼠标置换、物品拖拽等效果):

void Update(){
    
    

	// 获取需要移的动物体的屏幕坐标
	Vector3 followObjScreenPos = Camera.main.WorldToScreenPoint(followObj.transform.position);
	Vector3 mouseScreenPos = Input.mousePosition;

	// 补齐鼠标坐标缺失(为0)的z坐标
	mouseScreenPos.z = objScreenPos.z;
	Vector3 mouseWorldPos = Camera.main.ScreenToWorldPoint(mouseScreenPos);
	followObj.position = worldPos;
}

思路来源1:解决Unity鼠标坐标点转成世界坐标系坐标点
思路来源2:Unity 屏幕坐标转换世界坐标之物体跟随鼠标移动

猜你喜欢

转载自blog.csdn.net/weixin_44045614/article/details/108489738