Why is my character collision working for moving to the right, but not to the left?

I am trying to create a boundary for my level in Unity 3d, and I do not want my character to be able to move past a certain value on the x-axis. It works for the right side, I can move right and my character doesn’t go past LevelBounds.rightSide. However, for the left side, once I hit LevelBounds.leftSide, my character gets stuck and I can no longer move anymore. I am also noticing that the x position actually exceeds the LevelBounds.leftSide. Here is my update() function:

void Update()
{
    horizontalInput = Input.GetAxis("Horizontal");
    if (this.gameObject.transform.position.x > LevelBounds.leftSide)
    {
        transform.Translate(Vector3.right * Time.deltaTime * turnSpeed * horizontalInput);
    }
    if (this.gameObject.transform.position.x > LevelBounds.rightSide)
    {
        transform.Translate(Vector3.left * Time.deltaTime * turnSpeed * horizontalInput);
    }
    player.transform.Translate(Vector3.forward * Time.deltaTime * speed);
}

There are actually more problems here than you seem to realize.

You’re actually only able to MOVE by coincidence!

So, let’s unpack this to help you grasp what is happening.

horizontalInput = Input.GetAxis("Horizontal");

With that, you have a value between -1 and 1.

if(transform.position.x > LevelBounds.leftSide)

This will generally be true. If you’re to the right of the left edge, you’re in-bounds, so…

transform.Translate(Vector3.right * Time.deltaTime * turnSpeed * horizontalInput;

You will always attempt to move on every frame, scaled by your “horizontalInput”.

if(transform.position.x > LevelBounds.rightSide)

This will generally be false. You have to move beyond the right edge in order for this to become relevant. Plus, as an if rather than an else if, it will trigger in addition to the previous statement.

transform.Translate(Vector3.left * time.deltaTime * turnSpeed * horizontalInput);

Here’s where things get weird (and again, only works by coincidence). This moves you in the opposite direction based on the SAME input.

When you are at the right edge, you attempt to move further right (first if statement). This puts you beyond the right edge. Then, you’re shoved back in-bounds because the same input sends you back to where you started (second if statement), but only because you’re out of bounds and the second if statement became true.


Essentially, if your second if statement wasn't faulty, you would move, then move back to the same position on every frame. You wouldn't actually go anywhere if things were working "as intended".

This is also why this entire approach doesn’t make much sense!

Instead, let’s take a different approach to this to try and simplify EVERYTHING.

void Update()
{
	horizontalInput = Input.GetAxis("Horizontal");
	// Only process movement if input is provided
	if(horizontalInput != 0f)
	{
		// To keep this constrained to a single position
		// change, I'm setting position rather than
		// using Transform.Translate()
		Vector3 activePos = transform.position;
		activePos.x += turnSpeed * horizontalInput * Time.deltaTime;
		activePos.x = Mathf.Clamp(activePos .x, LevelBounds.leftSide, LevelBounds.rightSide);
		transform.position = activePos;
	}
	player.transform.Translate(Vector3.forward * speed * Time.deltaTime);
}

In this situation, when input is provided, the position will update based on a clamped horizontal value, both to ensure it remains in the correct range, as well as to allow you to reach the exact edges, rather than just getting very, very close.