Unity Editor Extension - Convert screen coordinates to world coordinates in Editor mode

I'm going to complain. I've been working on Unity's editor expansion recently. There are a lot of difficulties in it, but it's not to the point where I can't understand it. But when it comes to coordinate conversion, I can't figure it out.

I don’t know this unless I check it, but I’ll be surprised when I check it. Unity has many coordinate systems, including world coordinates, screen coordinates, local coordinates, window coordinates, etc., and each one is a different coordinate system, so about the coordinates of Unity Transformation is quite troublesome, but it is actually not a problem. There are many ready-made answers, provided that it is not operated in Editor mode.

The problem is that I just want to do editor expansion, so I encountered an almost blank field. It’s not that there are no relevant articles. There are articles about coordinate system conversion under editor expansion, but in my case they were all wrong. I was confused, and even wanted to write a function directly to implement it, but after grinding for a day and night, I saw the problem by chance.


Table of contents

Describe the problem

problem lies in

Solution


Describe the problem

I am making a 2D game. In an expanded window in edit mode, I need to select scene coordinates for a piece of data. The first thing I thought of was to convert the mouse position into world coordinates. There are various questions, but most of them can be answered on Baidu. However, there is a problem with the key coordinate conversion, and I can't get the data I want.

problem lies in

(Pictures I found randomly)

P1: The coordinate position within the P2 object that I need to convert, that is, the position of the mouse click

P2: The position point of an object

P3: The position of the upper left corner of the scene window

P4: The position of the lower left corner of the scene window

The code to obtain the coordinates of P1 is as follows

    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);
            }
        }
    }

The Input class cannot be used in edit mode, so the scene event class is used. The RectTransformUtility.ScreenPointToLocalPointInRectangle method will not be introduced in detail. Simply speaking, it converts the screen coordinates to the coordinates within an object. It is quite humane, but it is not It's a bit torture to use when you feel it through. The RectTransformUtility class has other conversion methods, and there are quite a few answers on Baidu.

At first, I used Event.current.mousePosition to get the mouse position. I wanted to convert P1 from screen coordinates to world coordinates. I used the conversion function that comes with Camera, which is wrong. Because the coordinates of P1 are not correct data, not accurate screen coordinates.

Commonly used coordinate systems include these

The coordinates of P1 are in the GUI coordinate system and cannot be directly converted. The mouse coordinates obtained by Event.current.mousePosition are GUI coordinates. They need to be converted to the Screen coordinate system before they can be used.

That is to say, P3 is the origin of the GUI coordinate system, and P4 is the origin of the screen coordinate system. P1 is in the coordinate system of P3, and P2 is in the world coordinate system. In short, the transformation is performed in this messy coordinate system.

Solution

    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;
    }

What this function returns is the accurate screen coordinates, converting the coordinates of the GUI coordinate system into the Screen coordinate system. I directly took the code from the Internet and changed it. Because it is a 2D project, it should have nothing to do with the Z axis, and of course it cannot. It is set on the back of the camera, so I won’t talk about it.

Source of the above code: Unity gets the world coordinates of the mouse position under the Scene window_BRK Xiaobu's blog-CSDN blog_unity gets the window position

The source code can be directly converted into world coordinates. I think it is also possible to use Camera's conversion function. It depends on the situation. The source code cannot be converted into a coordinate system within an object.

Summarize

Damn Unity, coordinate conversion is killing people, but once you understand this content, you will basically be able to encounter similar problems in the future.

First figure out which coordinate system the acquired coordinates are in, and then convert to the corresponding coordinate system. By the way, part of the reason is because I used the wrong Camera. There are two Cameras in my project, but they are both wrong. This should actually be a pitfall, and I still don’t understand it. It took me a long time to test this. After testing that, I finally changed to sceneView.camera to get the correct data. Is there a hidden camera? I’m not sure. If you use the OnSceneView (SceneView sceneView) event function, just use the sceneView.camera camera directly. Yes, probably (⊙_⊙).

Finally, if I can help you, I have probably achieved the purpose of writing this article. I wish you all good luck.

Guess you like

Origin blog.csdn.net/weixin_49779414/article/details/127380072