发会牢骚,最近一直在做Unity的编辑器拓展,其中难的地方不少,但不至于到看不懂的地步,可一做到关于坐标转换的内容时把我弄不会了。
这个不查不知道,一查吓一跳,Unity的坐标系非常多,有世界坐标,屏幕坐标,局部坐标,视窗坐标等等,而且每一个都是不一样的坐标系,所以关于Unity的坐标变换都挺麻烦的,但其实也不是难题,有很多现成的答案,前提是不在Editor模式下操作。
淦就淦在我就是要做编辑器拓展,所以就遇到了几乎一片空白的领域。不是没有相关的文章,关于编辑器拓展下的坐标系转换是有文章的,但在我的情况下全都不对,我就纳闷了,甚至想要直接写函数去实现,不过在磨了一天一夜后在机缘巧合下给我看出了问题。
目录
描述问题
问题所在
解决办法
描述问题
我做的是2D游戏,在编辑模式下的一个拓展窗口内需要为一个数据选定场景坐标,我首先想到的是通过鼠标位置转换成世界坐标来实现。有各种各样的问题,不过大都可以在百度上找到答案,只是关键的坐标转换却出了问题,我死活都拿不到想要的数据。
问题所在
(随便找的图)
P1:我需要转换的P2物体内的坐标位置,即鼠标点击的位置
P2:某物体的位置点
P3:场景窗口的左上角的位置
P4:场景窗口的左下角的位置
获取P1坐标的代码如下
private void OnSceneView(SceneView sceneView)
{
//鼠标左键点击判断
if (Event.current.type == EventType.MouseDown && Event.current.button == 0)
{
Vector2 newPosition;
//P2指P1所需要转换的位置的父物体
Transform P2 = GameObject.Find("P2").transform;
//坐标转换
RectTransformUtility.ScreenPointToLocalPointInRectangle(P2.GetComponent<RectTransform>(), GetMousePos(), sceneView.camera, out newPosition);
Debug.Log(newPosition);
}
}
}
Input类没法在编辑模式下用,所以用场景事件类,而RectTransformUtility.ScreenPointToLocalPointInRectangle这个方法就不多介绍了,简单来说就将屏幕坐标转换为某个物体内的坐标,挺人性的,就是没摸透时用有点折磨。RectTransformUtility类还有其他转换方法,百度上挺多答案的。
一开始我用Event.current.mousePosition来获取鼠标位置,我想将P1从屏幕坐标转换为世界坐标,用的是Camera自带的转换函数,是错的。因为P1的坐标不是正确的数据,不是准确的屏幕坐标。
常用的坐标系有这几个
而P1的坐标是GUI坐标系的,不能直接拿来转换。Event.current.mousePosition获取的鼠标坐标是GUI坐标,需要先将其转换为Screen的坐标系,转换为屏幕坐标才能用。
也就是P3是GUI坐标系的原点,而P4是屏幕坐标系的原点,P1在P3的坐标系下,P2在世界坐标系下,总之在这乱成一锅粥的坐标系下进行转换。
解决办法
public static Vector3 GetMousePos()
{
SceneView sceneView = SceneView.currentDrawingSceneView;
//当前屏幕坐标,左上角(0,0)右下角(camera.pixelWidth,camera.pixelHeight)
Vector2 mousePos = Event.current.mousePosition;
//retina 屏幕需要拉伸值
float mult = 1;
#if UNITY_5_4_OR_NEWER
mult = EditorGUIUtility.pixelsPerPoint;
#endif
//转换成摄像机可接受的屏幕坐标,左下角是(0,0,0);右上角是
(camera.pixelWidth,camera.pixelHeight,0)
mousePos.y = sceneView.camera.pixelHeight - mousePos.y * mult;
mousePos.x *= mult;
//近平面往里一些,才能看到摄像机里的位置
Vector3 fakePoint = mousePos;
fakePoint.z = 10;
return fakePoint;
}
这个函数返回的就是准确的屏幕坐标,将GUI坐标系的坐标转换为Screen坐标系下的,我是直接拿网上的代码改了一下,因为是2D项目,所以应该和Z轴没关系,当然也不能设置在相机背面,这点就不说了。
上面的代码出处:Unity获取Scene窗口下的鼠标位置的世界坐标_BRK小布的博客-CSDN博客_unity 获取窗口位置
源码直接转成世界坐标,我想用Camera的转换函数也行,看情况吧,源码没法转换成某个物体内的坐标系。
总结
淦他娘的Unity,坐标转换弄死人了,不过弄懂了这块内容基本上以后遇到类似问题就大致有数了。
首先弄清楚获取的坐标到底是在哪个坐标系下的,然后再转换到对应的坐标系就行了。对了,有部分原因是因为用的Camera弄错了,我的项目里有两个Camera,但都是错的,这其实也应该是一个坑,而且还没搞懂,弄了好久,测这测那的,最后是换成了sceneView.camera才拿到了正确的数据,难道还有隐藏的摄像机,不太清楚,如果是用的OnSceneView(SceneView sceneView)事件函数,直接用sceneView.camera这个摄像机就行了,大概(⊙_⊙)。文章来源:https://www.toymoban.com/news/detail-438526.html
最后,能帮到你就大概达到了写这个文章的目的,祝各位好运。文章来源地址https://www.toymoban.com/news/detail-438526.html
到了这里,关于Unity编辑器拓展——Editor模式下屏幕坐标转换为世界坐标的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!