Vector3.Distance on a 2d plane, not returning correct results

Hello there,

not new to coding/modding games in general, but “somewhat” new to Unity and C# coding. I have a very explicit problem I’m trying to solve.

I’m correctly using Vector3.Distance with a static height plane on a 2d editor for Stellaris. The third vector actually mimics the Camera.main.fieldOfView. So why? Because using a Vector2 does not correctly return the numbers I need when zooming in/out to my editors plane. For better understanding I’ll upload an image of what I’m doing.

It is a Galaxy editor for the game Stellaris, allowing you to place star systems. And for this editor I’m trying to build a “yardstick” like behaviour, trying to measure the distance between two points. My problem is, the returned distance has always added values based on how far I’m out of the Camera.Main.position(0, 0, 460). Here’s the code:

Update block

    void Update () {
        Vector3 pos1 = new Vector3();
        Vector3 pos2 = new Vector3();
        GameObject obj1;
        GameObject obj2;
      
        if (Input.GetKeyDown (KeyCode.Mouse0)) {
            Vector3 poss = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 460));
            GameObject anchorObject = (GameObject)Instantiate(anchorInst, new Vector3(poss.x, 0, poss.z), Quaternion.identity);
            obj1 = anchorObject;
            pos1 = obj1.GetComponent<Transform>().position;
            firstPoint = true;
            message = pos1.ToString("F0");
        }
        if(Input.GetKeyDown (KeyCode.Mouse1)) {
            Vector3 poss = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 460));
            GameObject anchorObject = (GameObject)Instantiate(anchorInst, new Vector3(poss.x, 0, poss.z), Quaternion.identity);
            obj2 = anchorObject;
            pos2 = obj2.GetComponent<Transform>().position;
            secondPoint = true;
        }
        if (firstPoint && secondPoint) {
            message = "Distance: " + Vector3.Distance (pos1, pos2).ToString("F0");
            firstPoint = false;
            secondPoint = false;
        }
        if (Input.GetKeyDown (KeyCode.Keypad5)) {
            int widthInt = Convert.ToInt32(cam.pixelWidth / 2);
            int heightInt = Convert.ToInt32(cam.pixelHeight / 2 + 108);
            SetCursorPos (widthInt, heightInt);
        }
}

OnGUI block

        GUILayout.BeginArea(new Rect(5, 640, 200, 85));
        GUILayout.BeginVertical("box", GUILayout.Width(200), GUILayout.Height(85));
        mousePos.x = Input.mousePosition.x;
        mousePos.y = cam.pixelHeight - Input.mousePosition.y; //cam.pixelHeight is used to make mouse position 0,0 at the top left corner
        mousePoint = cam.ScreenToWorldPoint(new Vector3(mousePos.x, mousePos.y, 460)); //default 3rd variable ---> cam.nearClipPlane; 460 is used for correct coordinates, see upside!
        GUILayout.Box("Screen pixels: " + cam.pixelWidth + ":" + cam.pixelHeight);
        GUILayout.Box("Mouse position: " + mousePos.ToString("F0"));
        GUILayout.Box("World position: " + mousePoint.ToString("F0"));
        GUILayout.EndVertical();
        GUILayout.EndArea();

Initial more simple Update Block

    void Update () {
        Vector3 pos1 = new Vector3();
        Vector3 pos2 = new Vector3();
      
        if (Input.GetKeyDown (KeyCode.Mouse0)) {
            pos1 = mousePoint;
            firstPoint = true;
            message = pos1.ToString("F0");
        }
        if(Input.GetKeyDown (KeyCode.Mouse1)) {
            pos2 = mousePoint;
            secondPoint = true;
        }
        if (firstPoint && secondPoint) {
            message = "Distance: " + Vector3.Distance (pos1, pos2).ToString("F0");
            firstPoint = false;
            secondPoint = false;
        }
        if (Input.GetKeyDown (KeyCode.Keypad5)) {
            int widthInt = Convert.ToInt32(cam.pixelWidth / 2);
            int heightInt = Convert.ToInt32(cam.pixelHeight / 2 + 108);
            SetCursorPos (widthInt, heightInt);
        }
}

So what is happening? It’s complicated, at least for me as noob. If I start measuring the distance from the exact center of my screen(0, 0, 460) I would always return the correct distance, but as soon as I move anywhere in width or height(x/y planes), the numbers will add a variance resulting in wrongly returned numbers. I do understand the problem is based on me using the Camera.Main, as initial “anchor” with cam.ScreenToWorldPoint. But I can’t find the solution to solve this issue.

At one point I was trying to first do the math on centering the intial anchor to exactly (0, 0, 0 <— respectively 460), and then add the coordinates for distance comparison to this initial set of vectors. I got closer to what I want, but still not perfectly hit the spot. Any ideas?

Solved the problem by using two static Transform objects.

Edit: how do you do that?

  1. create two empty GameObjects in the hierarchy
  2. add to them, depending on the shape you want(it was sphere for me)

a. Sphere (Mesh Filter)
b. Sphere Collider
c. Mesh Renderer

all default settings, make sure to use a appropriate material

  1. use any variation of this code snippet, to style the behaviour for personal preference
Vector3 mouseVector = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 460);//460 is the static height of my camera, you maybe want to use Input.mousePosition.z?
posTrans1.position = Camera.main.ScreenToWorldPoint (mouseVector);

You can also add a line renderer to your first Transform object, to display a visual “connection” between the two transform points, like this:

                posTrans1.gameObject.GetComponent<LineRenderer> ().SetPosition (0, posTrans1.transform.position);
                posTrans1.gameObject.GetComponent<LineRenderer> ().SetPosition (1, cam.ScreenToWorldPoint(mouseVector));

For sure you wanna make extensive use of booleans, if you apply this via key press etc.

1 Like