-1
\$\begingroup\$

I have a game object that has specific boundaries. However, when I have the object meet the boundaries, the object doesn't stop the way it's supposed to, it continues to move past the set boundaries. Can anyone explain why this would be happening and how to fix it?

Player Object public variables

enter image description here

C#

using UnityEngine;
using System.Collections;

public class PlayerController:MonoBehaviour{
    public Rigidbody player;
    public float bankSpeed;
    public float bankRotation;
    public float pitchSpeed;
    public float pitchAngle;
    public float xMin, xMax, yMin, yMax;
    public ChangeCamera changeCamera;
    void Start(){
        player = GetComponent<Rigidbody>();
        changeCamera.isThirdPersonView = false;
        changeCamera.isTopDownView = false;
    }

    void FixedUpdate(){
        if(changeCamera.isThirdPersonView == true){
            changeCamera.isTopDownView = false;
            thirdPersonControls();
        }
        if(changeCamera.isTopDownView == true){
            changeCamera.isThirdPersonView = false;
            topDownControls();
        }
    }

    void topDownControls(){
        float moveVertical = Input.GetAxis("Vertical");
        float moveHorizontal = Input.GetAxis("Horizontal");
        Vector3 bank = new Vector3(moveHorizontal, 0f, 0f);
        Vector3 moveForward = new Vector3(0f, 0f, moveVertical);
        player.AddForce(bank * bankSpeed);
        player.AddForce(moveForward * pitchSpeed);
        topDownRotation();
    }

    void thirdPersonControls(){
        float moveVertical = Input.GetAxis("Vertical");
        float moveHorizontal = Input.GetAxis("Horizontal");
        Vector3 bank = new Vector3(moveHorizontal, 0f, 0f);
        Vector3 pitch = new Vector3(0f, moveVertical, 0f);
        player.AddForce(bank * bankSpeed);
        player.AddForce(pitch * pitchSpeed);
        thirdPersonRotate();
    }

    void topDownRotation(){
        player.rotation = Quaternion.Euler(0f, 0f, (player.velocity.x * -bankRotation));
        player.position = new Vector3(Mathf.Clamp(player.position.x, -15.25f, 15.25f), 0f, Mathf.Clamp(player.position.z, 1f, 18.25f));
    }

    void thirdPersonRotate(){
        player.rotation = Quaternion.Euler((player.velocity.y * -pitchAngle), 0f, (player.velocity.x * -bankRotation));
        player.position = new Vector3(Mathf.Clamp(player.position.x, xMin, xMax), Mathf.Clamp(player.position.y, yMin, yMax), 0f);
    }
}

Basically, the way it works is, the player moves in any direction(up, down, left, right) and when they hit the edge of the screen, they're supposed to stop, which they do, however, if they continue to press the button that moves them, they'll continue to move off screen, very slowly. How do I prevent this from happening?

Dropbox Link

\$\endgroup\$
0

2 Answers 2

1
\$\begingroup\$

When you use the Unity rigidbody physics to control the movement of an object (like implied by using AddForce) you should generally not manipulate its transformation directly. Doing so can cause lots of weird behaviours.

If you need to constrain objects, place an invisible object with an appropriately shaped collider in the way.

Regarding why this is happening in this case, what happens every frame is:

  • You add a force to the object with AddForce
  • You set the transform.position
  • Code execution leaves your code and enters the Unity physics engine, which:
    • Checks the current forces added to the object
    • Calculates an acceleration vector
    • Adds that acceleration vector to the current speed vector
    • moves the object by that speed, beyond the position limit you set through clamping
  • The frame is rendered to the screen

The object slowly moves further into the "forbidden zone" every frame because the player adds more and more speed to it which translates to a further and further offset.

\$\endgroup\$
4
  • \$\begingroup\$ So, add an invisible bounding box with a rigid body component attached? If I'm not supposed to manipulate the transform directly, what do I need to manipulate? \$\endgroup\$
    – Robert
    May 14, 2016 at 14:25
  • \$\begingroup\$ I appreciate the info, but how do I actually stop this from occurring? Adding a box collider is not preventing it from happening \$\endgroup\$
    – Robert
    May 14, 2016 at 14:42
  • \$\begingroup\$ @Robert No rigidbody is needed on the bounds, just a collider with isTrigger off. A rigidbody on the bounds would be counter-productive as it would make the bounds themselves be affected by physics. You should not use a box but rather a set of planes around the borders of your playing-field. \$\endgroup\$
    – Philipp
    May 14, 2016 at 14:42
  • \$\begingroup\$ So I've added a single plane to test what you're telling me. The trigger is off, there is no rigid body attached to the plane, and the same exact issue I'm having is still occurring. Suggestions? Here's the updated link if you want to take a look. dropbox.com/home?preview=Space+Shooter+2.0.zip \$\endgroup\$
    – Robert
    May 14, 2016 at 15:02
-1
\$\begingroup\$

If you don't want to use planes or cubes to set the boundaries for your player object, the simplest way to accomplish this would be to remove the player object's velocity and angular velocity all together. Simply write a conditional which checks to see if the player object's position is at the desired boundary position. If it is, remove the velocity, like so:

if((player.position.x == xMin) || (player.position.x == xMax) || (player.position.y == yMin) || (player.position.y == yMax)){
    player.velocity = new Vector3(0f, 0f, 0f);
    player.angularVelocity = new Vector3(0f, 0f, 0f);
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .