Search Unity

Trying to clamp player to stay on screen

Discussion in '2D' started by douglinley, Feb 23, 2019.

  1. douglinley

    douglinley

    Joined:
    Nov 7, 2013
    Posts:
    5
    I've written a script to try to clamp a player object (or any object really) to the screen bounds. I'm doing something stupid somewhere but I have yet to find the stupid. I was hoping someone might be able to see what I'm doing.

    For reference, I'm in 2d orthographic mode.

    Here is how I move in my player script:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class PlayerController : MonoBehaviour
    4. {
    5.     public float moveSpeed;
    6.  
    7.     // Update is called once per frame
    8.     void Update()
    9.     {
    10.         var horizontalMove = Input.GetAxis("Horizontal");
    11.         var verticalMove = Input.GetAxis("Vertical");
    12.  
    13.         var movement = new Vector3(horizontalMove * moveSpeed * Time.deltaTime, verticalMove * moveSpeed * Time.deltaTime, 0f);
    14.  
    15.         transform.position += movement;
    16.     }
    17. }
    18.  
    Then I have a Boundaries script. I get the screen bounds by using Camera.main.ScreenToWorldPoint.

    I then get half the width and height of my object (which is just a triangle polygon for now) using the SpriteRenderer component bounds.size.x/y / 2.

    Then in LateUpdate() I attempt to clamp between the calculated positions. Here is the code:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3.  
    4. public class Boundaries : MonoBehaviour
    5. {
    6.     private Vector2 screenBounds;
    7.     private float objectWidth;
    8.     private float objectHeight;
    9.  
    10.     void Start()
    11.     {
    12.         screenBounds = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, Camera.main.transform.position.z));
    13.         objectWidth = transform.GetComponent<SpriteRenderer>().bounds.size.x / 2;
    14.         objectHeight = transform.GetComponent<SpriteRenderer>().bounds.size.y / 2;
    15.     }
    16.  
    17.     void LateUpdate()
    18.     {
    19.         Vector3 objectPosition = transform.position;
    20.         objectPosition.x = Mathf.Clamp(objectPosition.x, screenBounds.x + objectWidth, screenBounds.x * -1 - objectWidth);
    21.         objectPosition.y = Mathf.Clamp(objectPosition.y, screenBounds.y + objectHeight, screenBounds.y * -1 - objectHeight);
    22.         transform.position = objectPosition;
    23.     }
    24. }
    25.  
    What actually happens is the player appears to just clamp back and forth off screen at bounds outside of the screen area each frame and never shows up in the scene. I've checked all of the calculated values and they seem correct, so I can't figure out why.

    Here is a screenshot of the scene when it is running:



    Any insight into what I've botched up?
     
  2. drcrck

    drcrck

    Joined:
    May 23, 2017
    Posts:
    328
    Code (csharp):
    1. screenBounds = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, Camera.main.transform.position.z));
    Okay you get the world space xyz of the top right corner of the screen
    Once, when the game starts
    Is your camera static?


    Code (csharp):
    1. screenBounds.x + objectWidth, screenBounds.x * -1 - objectWidth
    It doesn't seem to make much sense
    Why you're multiplying world space coordinates by -1?
    It can give you the bottom left corner only if camera is always in 0,0,0
     
  3. douglinley

    douglinley

    Joined:
    Nov 7, 2013
    Posts:
    5
    Thanks for taking the time to reply.

    To flip it to negative. The bounds would be 2.67 and -2.67 on the x.

    Anyway, this is resolved. I have the min and max values flipped in clamp which was constantly pushing me out of bounds. Raistael over on the discord helped me spot this.

    Here is the fixed code in Boundaries.LateUpdate():

    Code (CSharp):
    1. objectPosition.x = Mathf.Clamp(objectPosition.x, -screenBounds.x + objectWidth, screenBounds.x - objectWidth);
    2. objectPosition.y = Mathf.Clamp(objectPosition.y, -screenBounds.y + objectHeight, screenBounds.y - objectHeight);