Stop forces from acting on object?

I’m using AddForce to move an object.

thisRigidbody2D.AddForce(Vector2.up * chargeSpeed, ForceMode2D.Force);

So the object’s velocity doesn’t change.

But I want to have the object fully stop after 1 second. Since velocity isn’t being altered, setting Rigidbody2D.velocity to 0 won’t do anything.

Is there a way of removing forces from an object? Or should I be changing the object’s velocity to create movement (so that I can just set it to 0 when I need it to stop)?

P.S. Whether the movement is static or smooth doesn’t really matter to me at this stage.

Set velocity to Vector2.zero and angularVelocity to 0.
Set gravityscale to 0 if gravity is acting on it.

Like I said, velocity isn’t affected by AddForce. It stays at 0 while the object is moving, so setting it to 0 does nothing.
Could you suggest a velocity alternative to AddForce so it behaves the same (or at least similarly)?

e.g.

thisRigidbody2D.velocity = // Something here

Also I just realized, apparently adding velocity to the object, doesn’t actually make it move.

Okay, update.

I did something I tried before that didn’t work… And somehow it’s working now.

thisRigidbody2D.AddForce(mouseDir * 0, ForceMode2D.Force);

So I can stick with my AddForce method for now.

Also I needed to add some IF checks here and there. Because I left my AddForce that moves the player, inside FixedUpdate right after an IF check that runs until I set a boolean to true. I thought if I set the boolean back to false, the code wouldn’t run past that IF check, so the AddForce wouldn’t be re-run and cause the player to keep moving after I stopped them… But apparently that wasn’t the case. So I just had to put the AddForce into an IF check, checking for the boolean being true.

Short version:
I had to change this.

void FixedUpdate () {
    if (bool == false) {
        //do stuff
    }
 
    thisRigidbody2D.AddForce
}

Into this.

void FixedUpdate () {
    if (bool == false) {
        //do stuff
    }
 
    else {
        thisRigidbody2D.AddForce
    }
}

Now everything is working fine, and the object is stopping after the desired time.

Disabling the gameObject and making it active again always seems to work for me,
Try it !

  private void RemoveAllForces()
    {
        gameObject.SetActive(false);
        gameObject.SetActive(true);
    }
1 Like

*No experience with 2D physics so take what I say with a bit of doubt.

So velocity is always 0 and you move it with AddForce?
Sounds like a bug, add force gives you velocity and the object moves through it.
how are you reading the velocity?

thisRigidbody2D.AddForce(mouseDir * 0, ForceMode2D.Force);

this should literally do nothing, it’s like saying

thisRigidbody2D.AddForce(Vector2.zero, ForceMode2D.Force);

is setting it kinematic on and off works too?
if so, you should probably do that because that way you don’t have to toggle the entire object and it’s children.

I’m reading the velocity by expanding the Rigidbody’s “Info” dropdown.

And you’re right, adding a force of “mouseDir * 0” shouldn’t work, because it’s adding a force with no value in any direction, but it works somehow.

I’ve read somewhere that AddForce applies external forces, and that’s why it doesn’t directly alter the Rigidbody’s velocity, though as an object is moving it’s velocity should still change in the Info section. Maybe it is a bug, but this happened every time I’ve ever used AddForce as far back as I can remember.

I haven’t tried using Kinematic, but the object is expected to constantly be colliding with other objects, so setting it to Kinematic even for a second could yield unnatural behaviors.

I don’t recall this being a thing, but maybe it’s just a 3D-2D mismatch.
Did you try Debug.Log()? the inspector window sometimes doesn’t update until you refocus on it.

When you add a force to a body then it doesn’t affect the velocity until the simulation runs at which point all the forces added to the body are integrated. You may not see a change in velocity if there are opposing forces i.e. collision, other manually added forces etc. All of that force won’t be added to the velocity either, it’ll be time-integrated.

If you add a force as an impulse then it’s added to the velocity directly and is the same as adding it to the velocity yourself. You get the full impulse force this way.

There’s some detail here.

Note: You can see the source-code if you look at “b2Body::ApplyForce” here (line 740) effectively adding the force you add to a total including totalling any torque that would be induced too. Both these linear and angular (torque) forces are added here (lines 206-207) with the linear force be added to velocity (v) scaled by the inverse-mass of the body with the addition of gravity and its scale then scaled by the delta-time (h). In other words, total all user forces then add them during the time-step scaled by the delta-time and the inverse-mass with the addition of gravity. You should see there’s no impulse force here, that’s added immediately to the velocity if you look at “b2Body::ApplyLinearImpulse” (line 798) above.

2 Likes

Using Vector3.zero for both the rigidbody.velocity and rigidbody.angularvelocity will stop the object and remove those forces.

If you want to slow the object down over time, here is an example using the new Input System:

PlayerInput playerInput;
    float mainThrust = 100f;
    private Vector2 thrustInput;

    void ThrustMovement() //Using the new Input System
    {
        //Input Action OnThrust bound to Directional Gamepad with normalized Vector2 processing
        thrustInput = playerInput.actions["OnThrust"].ReadValue<Vector2>();

        //Be sure to remove default deadzones on Input Action in the Project Settings > Input System Package
        if (thrustInput.y > 0.1f || thrustInput.y < -0.1f)
        {
            rb.AddRelativeForce(Vector3.forward * thrustInput.y * mainThrust * Time.fixedDeltaTime);
        }

        else
        {
            if (rb.velocity.z > 0.05f)
                rb.AddRelativeForce(Vector3.forward * -mainThrust * 2 * Time.fixedDeltaTime);
            else if (rb.velocity.z < -0.05f)
                rb.AddRelativeForce(Vector3.forward * mainThrust * 2 * Time.fixedDeltaTime);
            else
                rb.velocity = Vector3.zero;
        }
    }

    private void FixedUpdate()
    {
        ThrustMovement();
        YawMovement(); //Not in this example
        PitchMovement(); //Not in this example
    }

    public void OnThrust(InputAction.CallbackContext context)
    {
        thrustInput = context.ReadValue<Vector2>();
    }

Do you set it to zero in FixedUpdate or Update?

physics should happen in Fixed Update.