Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Resolved Camera/screen view staying inside the bounds of a larger level sprite?

Discussion in 'Scripting' started by johan-gl, Jun 30, 2023.

  1. johan-gl

    johan-gl

    Joined:
    May 26, 2013
    Posts:
    5
    I have an orthographic camera for a top down 2d game using a large sprite for the level terrain.
    The camera view is indicated by the blue rectangle in the screenshot.

    The level sprite is larger than the visible screen bounds and so extends beyond it, as seen in the green rectangle in the screenshot.

    When scrolling around on this level, how can i make sure the camera view stays inside the bounds of the level as seen in the screenshot for the B and C examples?

    I can get this to work with a fixed orthographic size by calculating bounds using the level sprite bounds, but as soon as i change the orthographic size (the player zooms in/out), my calculations are off and i cant seem to figure out a way to dynamically calculate this.

    I tried converting the level sprite corners to screen space and compare that to the screen bounds but it didnt turn out that well (issues snapping back to the edge if exceeding it) and i think it would be easier if i could just have the bounds check in non-screen space instead to avoid converting between them.

    Any idea how i can achieve this?

    example.png
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    Camera stuff is pretty tricky... you may wish to consider using Cinemachine from the Unity Package Manager.

    There's even a dedicated forum: https://forum.unity.com/forums/cinemachine.136/

    Otherwise this kind of "just stay within my bounds" stuff is always best done by explicitly authoring blank GameObjects at the lower left (least X/Y) and upper right (greatest X/Y) and using those GameObjects as your clamp inputs. I use that approach all over for movement, spawning, cameras, etc.

    Here is one I'm using now for my Jetpack Kurt Space Flight game's "level snapshotter"... I chose to make the references be Transforms rather than GameObjects, but either way.

    Screen Shot 2023-07-01 at 7.05.06 AM.png
     
  3. johan-gl

    johan-gl

    Joined:
    May 26, 2013
    Posts:
    5
    Thanks,
    Ive managed to use the blank gameobjects / anchors (and have also previously experimented with such a solution in another project) to get it to work vertically since thats what the ortho size is based on.

    Now, I basically check if the diff of the upper left anchorY - cameraY < cam.orthographicSize to detect if it has passed beyond its bounds and snap it back into place. I do the same but inverted on the bottom right vertical anchor.

    This then works nicely in any ortho size :)
    Is this the same approach you use?

    However, how do you calculate the horizontal edges since the ortho size is (to my knowledge) based on the vertical axis by default and my background is 1920x1080, so the width is a factor of roughly 1,7777 bigger than the vertical axis.

    In a full hd resolution (editor size), It appears that the camera x position of -4.8 is at the left edge and the upper left anchorX is -9.6, so the diff there is -4.8 (when the ortho size is at 2.7). The level sprite has a center pivot as well.

    Im doing some testing at the moment but -4.8 * 2 turns out to be the same as the edge at -9.6 so that appears to works at the default ortho size of 2.7, but not in any other size, so adding in the size and/or aspect ratio into the mix seems necessary.
     
    Last edited: Jul 1, 2023
  4. johan-gl

    johan-gl

    Joined:
    May 26, 2013
    Posts:
    5
    If anyone is interested, this is roughly the solution i came up with that works with any ortho size:

    Code (CSharp):
    1. var current = GetHitPoint();
    2.  
    3. var delta = (previous - current) * 0.9999f;
    4.  
    5. var position = cameraMain.transform.position;
    6. var x = position.x + delta.x;
    7. var y = position.y + delta.y;
    8.  
    9. var diffUpperLeft = anchors[0].transform.position - new Vector3(x, y, 0);
    10. var diffBottomRight = anchors[1].transform.position - new Vector3(x, y, 0);
    11.  
    12. if (diffUpperLeft.y < cameraMain.orthographicSize)
    13. {
    14.     y -= cameraMain.orthographicSize - diffUpperLeft.y;
    15. }
    16. if (diffBottomRight.y > -cameraMain.orthographicSize)
    17. {
    18.     y += diffBottomRight.y - -cameraMain.orthographicSize;
    19. }
    20.  
    21. var width = cameraMain.orthographicSize * cameraMain.aspect;
    22. if (diffUpperLeft.x > -width)
    23. {
    24.     x -= -width - diffUpperLeft.x;
    25. }
    26. if (diffBottomRight.x < width)
    27. {
    28.     x -= width - diffBottomRight.x;
    29. }
    30.  
    31. cameraMain.transform.position = new Vector3(x, y, position.z);
    32.  
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    Yes! Yes it is...

    Yep, I just use the ratio of the screen dimensions.

    With ortho camera:

    Code (csharp):
    1. float orthographicWidth = (Screen.width * cam.orthographicSize) / Screen.height;
     
    johan-gl likes this.