I'm not able to keep a sprite on-screen PROPERLY

So,been asking and google-ing for a massive ammount of time… ugh.

Basically,I have a sprite (a submarine…) and I want to move it on all directions without going off-screen.

I have this code that helps me a lot. I managed to move the sprite all by myself (ye,so proud),but I’ve got a code from somewhere else to keep that sprite inside the camera’s boundaries.

It works,sort of… half of the sprite HAS to go off-screen to stop going off-screen. And I seriously have no idea what to do. (I’m still learning if it wasn’t CLEAR ENOUGH)

Here’s that code I’m using:

using UnityEngine;
using System.Collections;

public class PlayerMovement : MonoBehaviour {

    public Camera cam;

    float maxSpeed = 6.5f;

    float widthRel = 1 / (Screen.width); //relative width
    float heightRel= 1 /(Screen.height); //relative height

    void Start () {
        if (cam == null) {
            cam = Camera.main;
            }
    }
    void Update () {

        //KEEP the sprite on the camera's boundaries.

        Vector3 viewPos = Camera.main.WorldToViewportPoint (this.transform.position);
        viewPos.x = Mathf.Clamp(viewPos.x, widthRel, 1-widthRel);
        viewPos.y = Mathf.Clamp(viewPos.y, heightRel, 1-heightRel);
        this.transform.position = Camera.main.ViewportToWorldPoint (viewPos);

        //MOVE the ship.

        Vector3 pos = transform.position;
        pos.y += Input.GetAxis("Vertical") * maxSpeed * Time.deltaTime;
        pos.x += Input.GetAxis("Horizontal") * maxSpeed * Time.deltaTime;
        transform.position = pos;

    }
}

One way to make sure that the whole sprite stays inside the boundaries is to separately check the edges.

On the left edge, you will compare the edge to the sprite position, minus the half-width of the sprite.
On the right edge, you will add the half width to the position.
Top and bottom are the same but with half-height.

I SADLY have no idea on how am I going to do that… maybe with public Bounds bounds;? Along with a ton of other stuff? xd

You can get the sprite’s dimension like this:

Vector2 spriteSize = GetComponent<SpriteRenderer>().sprite.bounds.size;
float halfWidth = spriteSize.x * 0.5f;
float halfHeight = spriteSize.y * 0.5f;

Definetly,I need to learn how to program properly… xd

halfWidth and Height are never used (obviously.) BTW,do I paste that code on the SAME ONE I’m using (and posted before),or should I make another script? D;

You can add code to your current script.

Try something like this:

Just a warning, this may or may not be a great way to do things in terms of efficiency. Also, I haven’t tested this.

    private Vector2 leftBottom;
    private Vector2 rightTop;
    private SpriteRenderer spriteRenderer;
    private Vector2 spriteSize;
    private Vector2 spriteHalfSize;

    private void Start()
    {
        // get the world location of the bottom left corner and top right corner of camera
        // if your camera moves, this will have to be in Update or LateUpdate
        leftBottom = Camera.main.ViewportToWorldPoint(Vector3.zero);
        rightTop   = Camera.main.ViewportToWorldPoint(Vector3.one);

        spriteRenderer = GetComponent<SpriteRenderer>();
        spriteSize     = spriteRenderer.sprite.bounds.size;
        spriteHalfSize = spriteRenderer.sprite.bounds.extents;
    }

    // do your normal movement in Update, then LateUpdate will correct the position before rendering
    private void LateUpdate()
    {
        // get the sprite's edge positions
        float spriteLeft   = transform.position.x - spriteHalfSize.x;
        float spriteRight  = transform.position.x + spriteHalfSize.x;
        float spriteBottom = transform.position.y - spriteHalfSize.y;
        float spriteTop    = transform.position.y + spriteHalfSize.y;

        // initialize the new position to the current position
        Vector3 clampedPosition = transform.position;

        // if any of the edges surpass the camera's bounds,
        // set the position TO the camera bounds (accounting for sprite's size)
        if(spriteLeft < leftBottom.x)
        {
            clampedPosition.x = leftBottom.x + spriteHalfSize.x;
        }
        else if(spriteRight > rightTop.x)
        {
            clampedPosition.x = rightTop.x - spriteHalfSize.x;
        }

        if(spriteTop < leftBottom.y)
        {
            clampedPosition.y = leftBottom.y + spriteHalfSize.y;
        }
        else if(spriteTop > rightTop.y)
        {
            clampedPosition.y = rightTop.y - spriteHalfSize.y;
        }

        transform.position = clampedPosition;
    }

Let me know if this works/doesn’t work, or if you want me to explain any parts.

“halfWidth,Height and spritebottom are assigned but its value is never used”

A random question that might solve some things: do I have to 100% COPY-PASTE the code,or do I HAVE to change some words (FOR EXAMPLE,this.Camera.camera) and change that camera for the name I assigned?

Don’t know if it’s clear enough… and sorry for bothering you with something so simple,I’m sure. xd

EDIT: The sprite starts in the middle of the camera,instead of the position I assigned. And also it doesn’t move. Probably because I posted the code in a wrong place. :V

The Camera class always keeps a reference to your main camera. So from anywhere you can do Camera.main and you’ll have the camera.

Here’s your class with my code pasted in the right places. It’s in your best interest to fully understand what is happening on each line, so feel free to ask more questions.

using UnityEngine;
using System.Collections;

public class PlayerMovement : MonoBehaviour
{

    public float maxSpeed = 6.5f;

    private Vector2 leftBottom;
    private Vector2 rightTop;
    private SpriteRenderer spriteRenderer;
    private Vector2 spriteSize;
    private Vector2 spriteHalfSize;

    private void Start()
    {
        // get the world location of the bottom left corner and top right corner of camera
        // if your camera moves, this will have to be in Update or LateUpdate
        leftBottom = Camera.main.ViewportToWorldPoint(Vector3.zero);
        rightTop   = Camera.main.ViewportToWorldPoint(Vector3.one);

        spriteRenderer = GetComponent<SpriteRenderer>();
        spriteSize     = spriteRenderer.sprite.bounds.size;
        spriteHalfSize = spriteRenderer.sprite.bounds.extents;
    }

    void Update()
    {
        //MOVE the ship.
        Vector3 pos = transform.position;
        pos.y += Input.GetAxis("Vertical") * maxSpeed * Time.deltaTime;
        pos.x += Input.GetAxis("Horizontal") * maxSpeed * Time.deltaTime;
        transform.position = pos;
    }

    private void LateUpdate()
    {
        // get the sprite's edge positions
        float spriteLeft   = transform.position.x - spriteHalfSize.x;
        float spriteRight  = transform.position.x + spriteHalfSize.x;
        float spriteBottom = transform.position.y - spriteHalfSize.y;
        float spriteTop    = transform.position.y + spriteHalfSize.y;

        // initialize the new position to the current position
        Vector3 clampedPosition = transform.position;

        // if any of the edges surpass the camera's bounds,
        // set the position TO the camera bounds (accounting for sprite's size)
        if(spriteLeft < leftBottom.x)
        {
            clampedPosition.x = leftBottom.x + spriteHalfSize.x;
        }
        else if(spriteRight > rightTop.x)
        {
            clampedPosition.x = rightTop.x - spriteHalfSize.x;
        }

        if(spriteTop < leftBottom.y)
        {
            clampedPosition.y = leftBottom.y + spriteHalfSize.y;
        }
        else if(spriteTop > rightTop.y)
        {
            clampedPosition.y = rightTop.y - spriteHalfSize.y;
        }

        transform.position = clampedPosition;
    }
}

There was some alerts,but well,they’re gone now. xd

The sprite itself now has to be a quarter or so off-screen to stop moving. Well,it’s better than before I guess.

I should say the sprite it’s a little bit wider than just a normal cube,FOR EXAMPLE. It’s basically this:

That’s why the sprite stops in random places… I think?

Nah the sprite’s bounds are always a box which encapsulates the whole thing. If you want to send me your project I could take a look if you’re comfortable doing that. I didn’t test any of that code so I’m not surprised if there’s some kinks in it. It also may be something else in your project that affects it, just speculating.

There’s always the solution of using box/edge colliders around the outside of the camera’s view if your camera doesn’t move.

I’ll just trash everything I made (trust me,it was NOTHING),and start all over again. From zero. Trying to learn and type my OWN “code”

Maybe that way I have less stupid problems…

Don’t worry man, just keep doing it and you’ll keep learning and getting better. Gotta be patient with yourself, programming a game is no easy task.