ray an
ray an

Reputation: 1288

Mathf.clamp() function in Unity

I have a Cube(Player) in my game scene. I have written a C# script to constrain the movement(using Mathf.Clamp()) of the Cube so it does not leave the screen.

Below is my FixedUpdate() method from the Script

private void FixedUpdate()
    {
        float moveHorizontal = Input.GetAxis("Horizontal");
        float moveVertical = Input.GetAxis("Vertical");

        Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
        rb.velocity = movement * speed;

        rb.position = new Vector3(
            Mathf.Clamp (rb.position.x, x_min, x_max),
            0.5f,
            Mathf.Clamp(rb.position.z, z_min, z_max)
            );

    }

Values of x_min, x_max, z_min, z_max are -3, 3, -2, 8 respectively inputted via the unity inspector.

PROBLEM

The script is working fine but my player(Cube) can move up to -3.1 units in negative X-AXIS (if I keep pressing the left arrow button) which is 0.1 units more in negative X-AXIS(This behavior is true for other axes too). It obviously clamps -3.1 to -3 when I stop pressing the button.

enter image description here

Upvotes: 3

Views: 11900

Answers (3)

Galandil
Galandil

Reputation: 4249

You already got the reason why this happens.

In order to fix the problem, you can use this code to prevent the cube to go outside your boundaries:

private void FixedUpdate() {
    Vector3 movement = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));

    // Get new position in advance
    float xPos = rb.position.x + movement.x * speed * Time.fixedDeltaTime;
    float zPos = rb.position.z + movement.z * speed * Time.fixedDeltaTime;

    // Check if new position goes over boundaries and if true clamp it
    if (xPos > x_max || xPos < x_min) {
        if (xPos > x_max)
            rb.position = new Vector3(x_max, 0, rb.position.z);
        else
            rb.position = new Vector3(x_min, 0, rb.position.z);
        movement.x = 0;
    }
    if (zPos > z_max || zPos < z_min) {
        if (zPos > z_max)
            rb.position = new Vector3(rb.position.x, 0, z_max);
        else
            rb.position = new Vector3(rb.position.x, 0, z_min);
        movement.z = 0;
    }

    rb.velocity = movement * speed;
}

Upvotes: 1

Tubeliar
Tubeliar

Reputation: 856

  • This is happening because the internal physics update moves the cube after you have put it in its clamped position. Mathf.Clamp() does restrict the cube to the expected position in the first place, as you can verify by putting a Debug.Log directly after you assign the position
  • You are getting the extra .1 units because you give the object a speed that gets applied after you clamp
  • It is 0.1 units because of the speed and the setting for Fixed Timestep (in Project Settings > Time). If you would set a higher speed it would be more. If you would lower the Fixed Timestep it would also be a bit more.

Upvotes: 4

Alox
Alox

Reputation: 671

Your issue could be caused because you are setting velocity and then position, but before the next frame unity adds the velocity to your objects position. Which is why it ends up 0.1 units off.

To fix this, try resetting the velocity of the object to zero if it's about to leave your boundaries.

Upvotes: 5

Related Questions