Convert Screen Width to distance in World Space

Hello,

I am working on a 2D game in which an Orthographic camera with variable size follows the player. I have a script that disables certain components (such as colliders and 2D shadow casters) when their objects are outside of a certain radius of the camera in order to increase performance.

Ideally, this radius should large enough that this is not visible on camera, but still as small as possible as to get the best performance levels possible. However, the orthographic size of the camera will be variable, so I cannot just use a fixed number for the radius.

Is there a way to convert Screen.width into a distance in world space, which I can use to determine the necessary radius at runtime? Is there a better alternative way of doing this?

Thanks so much and have a great day!

1 Like

Ortho cameras in Unity have always mapped to be orthographicSize equal to half the Screen.height.

From that you can infer the radius as a ratio of Screen.width to Screen.height.

Remember Screen.width and height are integers, so cast them to floats before dividing.

float aspect = (float)Screen.width / Screen.height;

float worldHeight = myCamera.orthographicSize * 2;

float worldWidth = worldHeight * aspect;

You can also just query the viewport position of the world object using the camera and this method:

Then if it is less than -0.1f or greater than 1.1f, you could consider that offscreen.

5 Likes

You can just multiply the orthographic size with the aspect ratio to get the horizontal size:

var orthographicWidth = cam.orthographicSize * cam.aspect;

Of course, whenever your orthographic size changes, you need to update your radius. But that is always the case, even if you convert Screen.width to world space units, this conversion also implicitly depends on the orthographic size and would need to be updated.

2 Likes

Thank you! But wouldn’t both of your solutions both give me a value in Screen Space, not world space?

Edit: I ended up trying your solution of using camera.WorldToViewportPoint, and that turned out to be perfect for me! Thanks so much!!

1 Like

Had a need for this functionality and my initial attempt used the logic above (thanks both) but…

On my setup (2D ortho, 54 ppu) I noticed that the logic introduced some rounding errors along the way. Only very small but enough that it resulted in a pixel overdraw.

After some experimenting I found that using the viewport resulted in no rounding errors, so ended up creating these two extension methods…

This one gets the screen rect (zero offset)…

  public static Rect GetScreenRect(this Camera value)
  {
    Vector3 topRight = value.ViewportToWorldPoint(new Vector3(1f, 1f, 0f));
    return (new Rect(0f, 0f, topRight.x * 2f, topRight.y * 2f));
  }

And this the screen rect in world space…

  public static Rect GetScreenWorldRect(this Camera value)
  {
    Vector3 bottomLeft = value.ViewportToWorldPoint(new Vector3(0f, 0f, 0f));
    Vector3 topRight = value.ViewportToWorldPoint(new Vector3(1f, 1f, 0f));
    return (new Rect(bottomLeft.x, bottomLeft.y, topRight.x * 2f, topRight.y * 2f));
  }

Not sure about the names and hot off the press (that is, only tested\confirmed under my setup) but thought some might find it useful if you hit the same issue.