Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Keeping the player within the boundaries of the camera

Discussion in '2D' started by lastcontract, May 12, 2014.

  1. lastcontract

    lastcontract

    Joined:
    May 12, 2014
    Posts:
    3
    Hi Everyone,

    As I go through some of the tutorials I'm also taking a day or two to mix in my own work. One of the things I am tackling at the moment is keeping the player sprite within the confines of the camera.

    Could you share your thoughts about my process below, if there is a better way to do these things, etc?

    First, I couldn't find a way programmatically to find the confines of the camera. What I decided to do was create some public variables:

    Code (csharp):
    1.     public float boundXleft = -10;
    2.     public float boundXright = 9;
    3.     public float boundYtop = 6.1f;
    4.     public float boundYbottom = -4.2f;
    I adjusted these values until I was happy with where my character could move and where it would get stuck. Is this the standard way of keeping a character within the camera? Will these values be different between devices (such as iphones/ipads)?

    I thought about creating rectangles on each side and (raycasting?) having the sprite collide. The issue is, I'll have enemies spawn slightly off screen - would they too collide? This is why I skipped raycasting (for now) and went with the method above.

    Then I do this for my touch movement withint the update method:

    Code (csharp):
    1.         // handle touch movement
    2.         if (Input.touchCount > 0  Input.GetTouch(0).phase == TouchPhase.Moved) {
    3.  
    4.             Vector2 touchDeltaPosition = Input.GetTouch(0).deltaPosition;
    5.             float myX = transform.position.x;
    6.             float myY = transform.position.y;
    7.             float newX = touchDeltaPosition.x;
    8.             float newY = touchDeltaPosition.y;
    9.  
    10.             // x boundaries
    11.             if(myX >= boundXright  newX >= 0){
    12.                 newX = 0;
    13.             }
    14.             if(myX <= boundXleft  newX <= 0){
    15.                 newX = 0;
    16.             }
    17.  
    18.             // y boundaries
    19.             if(myY >= boundYtop  newY >= 0){
    20.                 newY = 0;
    21.             }
    22.             if(myY <= boundYbottom  newY <= 0){
    23.                 newY = 0;
    24.             }
    25.  
    26.             // translation
    27.             transform.Translate(newX * speed, newY * speed, 0);
    28.  
    29.         }
    It works, but not effectively. If my character is moving too fast towards the right for example, the character may actually end up entirely off the screen. The code still works, it will prevent any further movement to the right - but I want to make sure the character truly stops at this point. Is there something better for me to do then transform.Translate?

    Thanks for your insights,
     
  2. Pyrian

    Pyrian

    Joined:
    Mar 27, 2014
    Posts:
    301
    Okay, let's tackle these one at a time.

    It's entirely possible to make colliders that do and do not interact with various categories of other colliders. You use Layers (not Sprite sorting layers, which are different). You create Layers in Project Settings->Input Layers, and then set which Layers collide with which other Layers in Project Settings->Physics 2D. Each Game Object has a Layer selection near the top in the Inspector. So, you can set a Layer for the Player, for the Enemies, for Level Geometry, and for the Level Boundaries, and then make the Enemies not collide with Level Boundaries.

    That being said... Translate movements ignore colliders anyway. You're not using physics to place your Player, then colliders would merely be for raycasting, and frankly that's not efficient for mere boundary tests (great for level geometry, though).

    Now, orthographic cameras have a fixed height in Unity units. So, you can set fixed colliders for the top and bottom. But the sides will then vary by aspect ratio. Here's my code to set left arrow/right arrow game objects based on the camera settings (this is IN the camera's script):

    Code (csharp):
    1. float OrthoWidth = camera.orthographicSize * camera.aspect;
    2. LeftArrow.transform.position = new Vector3 (transform.localPosition.x - OrthoWidth, 0.0F, 0.0F);
    3. RightArrow.transform.position = new Vector3 (transform.localPosition.x + OrthoWidth, 0.0F, 0.0F);
    ...I'm not quite sure why I'm using localPosition, it's a root object so I don't think it matters...

    Okay, now to your code. You're stopping the character from going any further once they hit a boundary, but you're not resetting them out of the boundary, so they end up partially out of the boundary. So, instead of setting the NewX to 0, you could set it to the distance by which they've exceeded the boundary, divided by your speed, so they'd always be translated to the edge.
     
    MaxPirat likes this.
  3. cbothra

    cbothra

    Joined:
    Mar 14, 2014
    Posts:
    125
    Code (csharp):
    1. var dist = (this.transform.position - Camera.main.transform.position).z;
    2.  
    3. var leftBorder = Camera.main.ViewportToWorldPoint(new Vector3(0,0,dist)).x;
    4. var rightBorder = Camera.main.ViewportToWorldPoint(new Vector3(1,0,dist)).x;
    5. var topBorder = Camera.main.ViewportToWorldPoint(new Vector3(0,0,dist)).y;
    6. var bottomBorder = Camera.main.ViewportToWorldPoint(new Vector3(0,1,dist)).y;
    7.  
    8. Vector3 playerSize = this.gameObject.renderer.bounds.size;
    9.  
    10. this.transform.position = new Vector3 (
    11. Mathf.Clamp(this.transform.position.x, leftBorder + playerSize.x/2, rightBorder - playerSize.x/2),
    12. Mathf.Clamp(this.transform.position.y, topBorder + playerSize.y/2, bottomBorder - playerSize.y/2),
    13. this.transform.position.z
    14. );
     
    Estema_TheWoz and MaxPirat like this.
  4. lastcontract

    lastcontract

    Joined:
    May 12, 2014
    Posts:
    3
    Thanks for your responses guys. I went a little while not getting back to you because my computer has been in the shop.

    Well you've given me two ways of tackling the it, but it sounds like setting the boundaries manually provides the best performance. I'm going to work on it a bit in the next couple of days. Thanks again!
     
  5. albertgelilov

    albertgelilov

    Joined:
    Mar 27, 2017
    Posts:
    1
    Hello, I know that it is an old post, but I will try.
    I got the wrong numbers I mean instead getting for rightBorder 20 I am getting 8.7 and the player is not even close to the edge of the right border of the screen.
    How can I fix it?

    Thanks for advance :)