Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question What is the origin of the use of addforce in Unity?

Discussion in 'Physics' started by cosmochristo, Dec 9, 2022.

  1. cosmochristo

    cosmochristo

    Joined:
    Sep 24, 2018
    Posts:
    250
    Hello, I am curious as to how and why the use of addforce came into being for the movement of player characters and vehicles. Was it all part of the inclusion of physics from the beginning?
     
  2. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,478
    It's in the essential foundation of simulating rigidbody dynamics. The state of the rigidbody is its momentum, both linear and angular. Simulating the evolution of the momentum involves integrating an ordinary differential equation (ODE) over time. This is what the physics solver does: it integrates the momentum of the rigidbody in each physics step. For that, it uses the derivative of the momentum. The derivative of linear momentum is Force, and the derivative of angular momentum is Torque.

    Here's a very good article describing the basic concepts of physics simulation:


    And here's a paper covering basic rigidbody dynamics simulation in depth:

     
    Marcos-Schultz and cosmochristo like this.
  3. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,851
    A simpler explanation: because objects in the real world don’t teleport. If something moves, it’s because a force is affecting it, you can’t change the position of an object instantly.

    If you want to somehow replicate this in a computer, you need to deal with forces and of course, this means being able to AddForce() to stuff.
     
  4. cosmochristo

    cosmochristo

    Joined:
    Sep 24, 2018
    Posts:
    250
    @Edy , @arkan022 and others: thanks for your answers. My question was probably not clear. I was not looking for explanations of addforce implementation and physics. I have a good understanding of that. In fact, most of my work is based on the position independent principle which is essentially the same as the physics principle of no absolute position that was proven by Newton's laws.
    What I was trying to determine, is how developers came to use addforce to move characters instead of just applying displacement = speed * deltatime. I think I will raise a new question that is clearer.
     
    Last edited: Dec 16, 2022
  5. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,851
    Because force and acceleration are not exactly the same thing, the effect a force has on an object depends on the mass of said object as you know. That of course doesn't add too much complexity so you could still do it yourself:

    Code (CSharp):
    1. speed = speed + force1 / mass * deltatime; // add some external force
    2. speed = speed + force2 / mass * deltatime; // add some other external force
    3. //.
    4. //.
    5. //.
    6. speed = speed + forceN / mass * deltatime; // add yet another external force
    7. position = position + speed * deltatime;
    But it becomes even more verbose when you throw angular velocities and rotations in the mix, since you have to deal with inertia tensors: then quaternions, 3x3 matrices and change-of-basis matrices start to pop up in your calculations.

    So for economy of typing and cleanliness, you might as well abstract all that stuff away into a single function such as AddForce(). There isn't anything in that function that you couldn't implement yourself, but since someone found himself writing the same chunk of ugly-looking code again and again he took the wise decision to package it all nice and tidy.
     
    Last edited: Dec 16, 2022
  6. cosmochristo

    cosmochristo

    Joined:
    Sep 24, 2018
    Posts:
    250
    Yes, I know. I did high school physics and some in University. :).
    Never mind - I will rephrase the question some time, but thanks for taking the time to share your thoughts.
     
    arkano22 likes this.
  7. Yuchen_Chang

    Yuchen_Chang

    Joined:
    Apr 24, 2020
    Posts:
    125
    If one do something like
    rigidbody.position += velocity * Time.deltaTime;
    or
    MovePosition()
    , the object will have a chance to penetrate through other objects (unity won't instantly simulate Physics); Adding a force or adjusting the rb.velocity will let Unity handle movement at the next Physics simulation step, without penetration.
    And About AddForce or set velocity when applying simple character movement, I think it's just one's choice. AddForce() is convenient, because you don't have to retrieve the velocity, do some calculations and put it back.
    (However I prefer adjusting velocity directly more)
     
    cosmochristo likes this.
  8. cosmochristo

    cosmochristo

    Joined:
    Sep 24, 2018
    Posts:
    250
    I prefer going directly with displacement based on velocity too. It does not have to be retrieved: once you have the starting velocity you will always know what it is - if not doing all the addforce etc.
    You are partly correct about the penetration but I find that it is easy enough to manage because every collision/penetration is recorded in the changes to rigidbody. Unless the physics goes to sleep - but I prevent that.

    Furthermore, I do not move the player at all: it stays at the origin. The collisions on RB occur when World is shifted in reverse around the player. Displacement is not on the player :)
     
  9. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,478
    In the case of Unity, using AddForce allows the underlying physics engine to resolve collisions with other characters and with the environtment. If you calculate the displacement yourself as speed * deltaTime, then you also need to write your own system for detecting and resolving collisions.

    Note that AddForce methods can be used not only to apply forces, but also can apply impulses and velocity deltas. One may use AddForce with ForceMode.VelocityChange to reach a specific velocity and the character will still detect and resolve collisions properly by itself.

    This is not a good practice. Writing to rb.velocity overrides the calculations of the physics solver, which may lead to inconsistencies and unexpected behaviors. AddForce with ForceMode.VelocityChange should be used instead.
     
    tsukimi likes this.
  10. cosmochristo

    cosmochristo

    Joined:
    Sep 24, 2018
    Posts:
    250
    Actually, that is incorrect. When something collides with the player rigidbody, it moves, regardless of how that collision came about. Relatively speaking, moving the world to collide with the player, or the player to collide with the world is the same relative movement.
    I have tested all this over many years and movement of the world around a zero-cetred player, using displacement not addforce works fine.
    For example, if you go to the "Arrival at planet-side scene, 8million meters away." bookmark in the attached video, you will see that the player does not penetrate the planet-side scene on arrival: it collides as you would expect with the environment.
     
  11. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,851
    Nope, what Edy said is 100% correct. Collision resolution usually involves:

    A) correcting object positions: in case they are intersecting, move them apart until they're no longer intersecting.
    B) correcting object velocities: using their mass, restitution and friction coefficients, calculate correct velocities after the collision.

    So if you move a rigidbody inside another object by doing position += speed * deltaTime, the engine will only get A) correct, B) will be completely botched. You'll need to write your own collision resolution method for a correct result.

    You can easily test this by placing a box on top of a platform, and then moving the platform sideways using position += speed * deltaTime: the box on top will not move with the platform, instead will be kept completely static as friction (used in step B) is not accounted for: you’re basically sidestepping the entire physics engine except for the collision detection pipeline and positional projection.

    However if you use AddForce() to move the platform, velocities -and all velocity dependant constraints/effects- are correctly taken into account and if friction is high enough, the box will move with the platform.

    Accurate collision response isn’t the only reason to use forces/accelerations, object velocities are also used for CCD (continuous collision detection) which will not work at all if calculating and applying displacements yourself. Yet another disadvantage is that you’re integrating velocity yourself, instead of allowing the engine to use its own integrator (oftentimes much more precise than basic Euler, RK4 is typically used)

    Then I'm sad to inform you that your tests were wrong. It may look like they're working properly because objects won't sink into each other, but results for everything except purely inelastic & frictionless contacts will be wildly inaccurate since you're relying on kinematic collision resolution only. This is kinda like leaving your car on neutral on a downhill slope and concluding that since it's moving, then its engine must be running.

    Only case where directly modifying the position of a body works reasonably well is in a position-based dynamics paradigm (which Unity does not use) since velocities are derived from positional deltas. This however comes with its own set of pitfalls.
     
    Last edited: Dec 16, 2022
  12. cosmochristo

    cosmochristo

    Joined:
    Sep 24, 2018
    Posts:
    250
    @arkano22
    yes, and unity does this for me. I don't prevent unity from doing it.
     
  13. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,851
    If you apply your own displacement (displacement = speed * deltaTime), you’re preventing Unity from doing any velocity calculations for you since your objects have zero velocity as far as Unity is concerned: you are essentially teleporting them around. This is what we are trying to tell you.

    The approach you described of keeping the player fixed at the origin of the scene’s reference frame and displacing planets around him essentially bypasses most of the physics engine: all Unity can do for you is project objects outside each other when they intersect. This might be enough for your use case, but for most applications it is not: restitution (bouncing) and friction won’t work, objects will have no momentum/inertia, joints won’t work, CCD won’t work, and a long etc.

    That’s why in most cases you should use AddForce instead: it applies a force to the object, which modifies its velocity, and allows Unity to perform accurate simulation because objects no longer have zero velocity. Note this isn’t specific to Unity: pretty much all physics engines you will come across use a velocity-based paradigm.
     
    Last edited: Dec 17, 2022
    cosmochristo likes this.
  14. cosmochristo

    cosmochristo

    Joined:
    Sep 24, 2018
    Posts:
    250
    Ok, thanks for making your thoughts clearer, now I have a much better idea of why you use addforce, thank you!

    I find that friction, momentum, reposes to changes to drag, mass, gravity all work. Perhaps they are not working the same, I don't know.

    A better example is linked below: Two player types: simple capsule and complex character with own external controller.
    Both have floating origin relative motion (they don't move from origin).

    Capsule bookmark: “With greater scene complexity, including stairs”
    External character bookmark: “Complex animated character with own cameras”

    Notes:
    1. The capsule player is not moved by "AddForce", just translation (of the World).
    2. The Externally controlled animated character (from GKC asset) is moved via AddForce.
    3. Both 1. and 2 negotiate the ramp and stairs naturally.