How to get equal screen coordinates on different resolutions?

Hello guys! Im currently making a game, where you need to outilne a symbol on screen, so easiest way i found is to store coordinates of a symbol and check if mouse is near and make calculations based on that. Everything works for me, but on diffrent resolutions in same spots mouse position is diffrent.

I came up with this script that scales positons perfectly, but i have an offset on x axis, how can i remove it?

Rect canvasSize = GameObject.Find("Canvas").GetComponent<RectTransform>().rect;

         Vector2 resolution = new Vector2((float) currentScreenSize.x / canvasSize.width, (float) currentScreenSize.y / canvasSize.height);

         corners.Add(new Vector2(385 * resolution.x, 890 * resolution.y));
         corners.Add(new Vector2(172 * resolution.x, 395 * resolution.y));
         corners.Add(new Vector2(550 * resolution.x, 395 * resolution.y));
         corners.Add(new Vector2(381 * resolution.x, 594 * resolution.y));

Reference resolution i have 720x1280, if resolution stays in the same ration like 360x640 everything is perfect, but other resolutions i have x offset.

Well, you are going to have to use numbers that are relative to screen width and screen height. If the object were centered. You would subtract the rectangle width from the screen width and divide by 2 to get the amount on each side of the rectangle. If you were going from left to right, with left being zero, then that would be the x value. The other side would be the x value plus the rectangle width.
As long as the object is centered, you should only need one formula for all resolutions. Probably simpler would be to find the center point and subtract or add 1/2 the width and height of the rectangle.

Maybe you can use canvas ui and use the outine as an image which appears or is on and off whenever you want to?

Thanks for reply, as you adviced i edited my code, so i if i change screen width, it fits perfectly, but can you help with height? :slight_smile:

Rect rect = GameObject.Find("Canvas").GetComponent<RectTransform>().rect;

        Vector2 resolution = new Vector2((float) currentScreenSize.x / rect.width, (float) currentScreenSize.y / rect.height);

        float xOffset = (720 - rect.width) / 2;


        corners.Add(new Vector2(385 * resolution.x - xOffset, 890 * resolution.y));
        corners.Add(new Vector2(172 * resolution.x - xOffset, 395 * resolution.y));
        corners.Add(new Vector2(550 * resolution.x - xOffset, 395 * resolution.y));
        corners.Add(new Vector2(381 * resolution.x - xOffset, 594 * resolution.y));




I’m glad that worked, but you are still kind of thinking in numbers. If you know the screen width and height, and the rectangle size, you don’t need any other numbers other than that.

Rect rect = GameObject.Find("Canvas").GetComponent<RectTransform>().rect;

int centerWidth = (int)currentScreenSize.x/2;
int centerHeight = (int)currentScreenSize.y/2;
int offsetY = (int)rect.height/2;
int offsetX = (int)rect.width/2;

//I don't know the order of your corners, but you add or subtract the offset of the rect from the center to get the corner
 corners.Add(new Vector2(centerWidth-offsetX,centerHeight-offsetY));

Just picture it in your mind. You find the center of the screen, then you subtract or add half the rectangle size to get the four corners.

Thanks for your reply! Im totaly confused by your answer, so basically i have i have 4 points that i found on 720x1280 resolution, using vectrosity i you can see them on a screen.

So im not looking for corners, im looking for several points, that actually represents a symbol. Considering that on different resolutions image will be smaller/bigger points also should be adapted this way.

Vector2 resolution = new Vector2((float) currentScreenSize.x / rect.width, (float) currentScreenSize.y / rect.height);

Vector 2 point = new Vector 2(x*resolution.x,y*resolution.y)

Just multiplying resolution variable i adapt my points to fit the symbol and it works perfectly, points are at exact positions they need to be, main problem is depending on where i have “Match” on width 0 or height 1, i have not correct x or y of all points.

Using some weird resolution like 500x1500, i have perfect points positions, but y or x are not correct.On first image Match is 0 on width, on second image Match is 1 on height.

How to place my points, so they are exactly like on resolution 720x1280?

I think you have to chart your points relative to the rectangle, not to a specific resolution. You start 1/4 down on the rectangle, 2/3 over from the left, etc. That will be the same no matter what resolution. I was just talking about finding the corners of the rectangle for any screen size. Because the aspect ratio is changing, what you are doing is going to be extremely difficult. You really need to use relative positioning.

I think that’s what you are doing, but you have to take the height and width separately, because the h/w changes, so you can only multiply by the height, and separately multiply by the width, not use them together in a formula, because then it will be dependent on the aspect ratio.

Say your x value was 100 and the screen width was 800. Then relative value is 1/8 the screen width. The height has to be done separately as a portion of the height. So if you multiply the value of the new screen width by 100/800 or whatever your resolution was, you will get that x position for the new screen width.

It would probably be safer to get a percentage of the rectangle, though. Anyway, hope that helps a little.

Thanks for your reply, i understood your idea, so its like this?

       corners.Add(new Vector2((float) 385 / 720 * currentScreenSize.x, (float) 890 / 1280 * currentScreenSize.y));
        corners.Add(new Vector2((float) 172 / 720 * currentScreenSize.x, (float) 395 / 1280 * currentScreenSize.y));
        corners.Add(new Vector2((float) 550 / 720 * currentScreenSize.x, (float) 395 / 1280 * currentScreenSize.y));
        corners.Add(new Vector2((float) 381 / 720 * currentScreenSize.x, (float) 594 / 1280 * currentScreenSize.y));

Now i have results like this, maybe i didnt understood, about height?

Well, you’re using an overlay canvas, which means you can take a simple shortcut. You can actually just store your points as world space, and they should be consistent on any resolution. Any changes you do in the Canvas Scaler component actually just modifies the RectTransforms scale and Rect values, which enables the RectTransform itself to be able to handle the conversions for you (via InverseTransformPoint). In fact on Overlay canvases the Mouse position value is actually the same value in screen space and world space.

From the looks of your code, it seems like you are writing, and wish to use, the positions in Rect space (i.e. relative to the Rect with the origin being bottom-left corner of the rect). You can use these functions in case you need to convert points back and forth from World space and rect space.

public static class RectTransformExtensions
{
    private static Vector3[] worldCorners = new Vector3[4];

    public static Vector2 WorldToRectCoordinate(this RectTransform rectTransform, Vector3 position_world)
    {
        if(!rectTransform) return Vector2.zero;

        rectTransform.GetWorldCorners(worldCorners);

        var position_origin = rectTransform.InverseTransformPoint(worldCorners[0]);
        var position_local  = rectTransform.InverseTransformPoint(position_world);

        var position_rect   = (Vector2)(position_local - position_origin);

        return position_rect;
      
    }

   
    public static Vector3 RectToWorldCoordinate(this RectTransform rectTransform, Vector2 position_rect)
    {
        if(!rectTransform) return Vector3.zero;

        rectTransform.GetWorldCorners(worldCorners);

        var position_origin = rectTransform.InverseTransformPoint(worldCorners[0]);
        var position_local   = (Vector3)position_rect + position_origin;

        var position_world  = rectTransform.TransformPoint(position_local);

        return position_world;
    }
}

with this you can, for example take the points on the white symbol (which you likely have in Rect space), convert them to world space using the rect transform they are on and use those world space points to assign points for the red symbol on a completely different RectTransform (which may be on a completely different overlay canvas) and the points will appear to sync up on both.