0
votes

I'm trying to add acceleration to an object with a RigidBody2D component using AddForce, but all it seems to do is add a fixed velocity instead.

Here are the RigidBody2D settings: RigidBody2D Settings

For testing I've modified the Update function to allow me to add forces and report the object's velocity periodically:

void Update()
{
    time += Time.deltaTime;
    if (time > 0.5)
    {
        Debug.Log("Velocity magnitude = " + rigidbody2D.velocity.magnitude);
        time = 0;
    }

    if (Input.GetKeyDown(KeyCode.Q))
    {
        rigidbody2D.AddForce(Vector2.right);
    }
}

What I see is that every time I press Q, the velocity magnitude increases by a fixed 0.02.

I.e. first it doesn't move at all and the velocity is 0, then after pressing Q the velocity magnitude changes to 0.02 and stays at 0.02 while the object trudges slowly to the right. Pressing Q again increases it to 0.04, then pressing once more increases it to 0.06 and so on.

These are results from two days ago. I did the experiment again today and got different velocity increments but the same behavior otherwise.

The velocity changes only when I add a force.

If I added a force of magnitude 1 to an object at rest with a mass of 1 then its velocity would increase by 1 in magnitude every single unit of time (which I think here is seconds).

Instead it's staying fixed.

Using ForceMode2D.Impulse increases the velocity increments from 0.02 to 1, but the behavior stays the same - no acceleration, only one-time increments in speed.

What am I doing wrong?


I've tried looking for similar posts and for the problem in general but the only things I found were either irrelevant or asking the opposite (how to stop acceleration from occurring).

Any help would be appreciated.

The Unity version is 2019.1.1f1.

2

2 Answers

1
votes

I don't think that's going to add enough force to the object to get it into motion. Normally you need to multiply your direction by a "force" multiple. Try something like rigidbody2D.AddForce(Vector2.right * 1000);. That is, intentianally, probably way too much force but at least you'll know it's moving.

1
votes

TL;DR

What you are doing wrong is that you are expecting the wrong physics behavior from the apply force function. That function does what it says, it applies force. It changes the object velocity instantaneously adding to it. The force mode for 2d bodies only tells the engine to consider the object's mass or not.

The problem is the naming Unity uses, AddForce doesn't "add" the force, it just applies the force for a single frame. In the following frames, all forces are zero again. If you want to keep the force, just create your own vector in your script, modify it, and apply it to the object every frame using AddForce.


how are you?

I have created a sample project to reproduce your issue but I couldn't reproduce the velocity staying fixed as you said. I'm not sure how you set up your scene so I made some assumptions. You probably have disabled either gravity on your object or friction, since you are reporting that the velocity is increased.

Acceleration, on the other hand, is a constant force being applied, think of it. If your car is still, and you push it for a short amount of time, the car will move then stop. If you keep pushing on the other hand, adding more and more force, the car will move faster and faster. Now think about your environment, you have a frictionless object. Every time you press Q you add a small force to it. It moves to the right a bit faster but with a constant speed (there is no force to change its velocity).

Here is what you'd want to do. Instead of adding the force only in the frame you pressed Q, add while you are pressing Q. This is what you want to do:

private void FixedUpdate()
{
    time += Time.deltaTime;
    if (time > 0.5)
    {
        Debug.Log("Velocity magnitude = " + rigidbody2D.velocity.magnitude);
        time = 0;
    }

    if (Input.GetKey(KeyCode.Q))
    {
        rigidbody2D.AddForce(speedMultiplier * Time.fixedTime * Vector2.right, ForceMode2D.Force);
    }
}

Another problem is the naming Unity uses, AddForce doesn't "add" the force, it just applies the force for a single frame. In the following frames all forces are zero again. If you want to keep the force, just create your own vector in your script, modify it, and apply it to the object every frame using AddForce.

Also, see that I changed Update to FixedUpdate? In Unity, you are recommended to apply all physics changes in that method instead. Update runs as much as it can (once every frame if possible), fixed update instead runs only after the physics thread is done. This means you are not spending CPU time telling the object to move every frame, and instead you are waiting for the physics to be synchronized.