项目场景:
游戏中经常需要通过点击屏幕,并且在点击位置的3D空间中创建一个物体。
问题描述
这个时候大多数同学可能会想到使用相机的屏幕坐标转换为世界坐标的方法,代码如下:
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
if (Item==null)
{
return;
}
var clickPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Debug.LogFormat("Screen:{0}//World:{1}", Input.mousePosition,clickPos);
var go = Instantiate(Item);
go.transform.position = clickPos;
go.transform.rotation = Random.rotation;
}
}
执行代码,出现所有的物体都创建在一个点上,Debug点击时的屏幕坐标和转换后的世界坐标,发现屏幕坐标没问题,但是不管点击在什么位置转换后的坐标全都是一个值。
这并不是我们想要的,那什么原因呢??
原因分析:
我们发现相机使用的是透视相机,那相机的视角就像是一个锥形,那有没有可能我们点击屏幕时都是点击在一个世界坐标点上,所以转换后的世界坐标就保持不变呢。针对这个猜测我们可以做两个尝试:
1.将相机改为正交相机;
2.转换坐标前的屏幕坐标向相机正前方偏移一段距离,这样就不是点击在一个点上了,简单理解就是三角形顶端和梯形的顶端的区别。
解决方案:
方案一:相机改为正交模式
发现坐标返回正确,不过有个问题,正交相机并不满足我的要求,我想要的是在透视相机下也能满足要求,那试试方案二。
方案二:
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
if (Item==null)
{
return;
}
var screenPos = Input.mousePosition;
screenPos.z = 5;
var clickPos = Camera.main.ScreenToWorldPoint(screenPos);
Debug.LogFormat("Screen:{0}//World:{1}", Input.mousePosition,clickPos);
var go = Instantiate(Item);
go.transform.position = clickPos;
go.transform.rotation = Random.rotation;
}
}
完美解决!!