Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Stopping a RigidBody2D

Discussion in '2D' started by JymWythawhy, Mar 10, 2017.

  1. JymWythawhy

    JymWythawhy

    Joined:
    Jan 18, 2015
    Posts:
    25
    I have a spaceship with "Asteroids" style movement- there is no drag, and you don't have to be going in the direction you are facing. The left and right keys rotate your ship, and the up key applies a force to the Rigidbody2D in the direction you are facing.

    That all works fine... What doesn't work great is stopping. If you hold down the down key, your ship rotates until it is facing directly away from the way your ship is heading. If you continue holding down the key, your ship applies a thrust force until you are close to stopping (a value around double what is added in a single physics step by the acceleration force). If the magnitude of the velocity is below that threshold, and the change in velocity is negative since the previous frame (the ship is stopping instead of starting), the thrust function sets the Rigidbody2D's velocity to 0... or at least it is supposed to.

    About half the time, there is some residual velocity that doesn't go away, even though I set it to zero. I put a Debug.Log call at the top of the Thrust function and one in the If statement that sets the velocity to zero, and I can see that the Thrust function is not being called after the velocity is set to zero, and that is the only thing that adds force to the rigidbody, so the velocity should stay zero, but it doesn't.

    Any ideas? I have tried setting the angular velocity to zero, and turning the RigidBody2D to kinematic briefly, but those didn't solve the problem either.

    Is this just a bug in the 2D physics? Should I just forgo using the Unity2D physics and move the sprite manually? I could keep track of the velocity vector and make adjustments to that based on the acceleration of the thrust and then apply the new Velocity times DeltaTime to the position each frame. It would be a shame not to be able to use the physics system for explosions though, but that should be doable through other means as well.
     
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,559
    You mean, 2D physics doesn't use forces correctly? There would be lots of screaming going on if that were the case. More likely, it's what you're doing. You're better off providing some simple script as an example rather than trying to explain it.

    If you set the velocity of a Rigidbody2D during FixedUpdate to zero, that doesn't reset any forces you've applied during FixedUpdate. Those will still get applied resulting in a non-zero velocity. If that's the case, you need to handle your thrust control differently.
     
  3. JymWythawhy

    JymWythawhy

    Joined:
    Jan 18, 2015
    Posts:
    25
    Haha Good point. I didn't mean bug as in the forces are not being applied correctly, but just that my attempts to stop all motion on an object when it is below a threshold speed were unsuccessful, so it the physics system wasn't behaving as I expected.

    I will try a minimal example and see if I can recreate the problem there, and post back with that if I do recreate it.

    In the meantime, setting the rigidbody2D drag to 2000 stops the motion extremely quickly, which might be a kind of hacky way of ensuring I can stop object motion.

    I've also had success just keeping track of a velocity vector and translating the gameobject every update based on that, so I might just stick with the simple solution until I run into some reason I shouldn't. (If you know such a reason, I would love to hear it!) Thanks.
     
  4. JymWythawhy

    JymWythawhy

    Joined:
    Jan 18, 2015
    Posts:
    25
    Thinking through it some more, I think the problem is as you described in your last paragraph. In my thrust function, I apply the force and then see if the new velocity is close to zero. If it is then I set the velocity to zero. But apparently that force still gets applied, causing the problem I'm seeing. Should I, in the same function, then apply exactly the opposite force, to cancel it out? Or start a coroutine that will zero the velocity during the next frame?

    Thank you for your help on this!
     
  5. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,559
    Currently we don't expose the 'accumulated' force that will get applied during the next FixedUpdate although it'd be super easy to do so and perhaps we should do that soon. Also, we currently don't expose a LateFixedUpdate (occurs after all FixedUpdate callbacks and Physics Update) but we'll be trying to get that in ASAP as well.

    Unless you keep track of what forces you've added, your only real option is to flag that you've added forces and zero velocity either in the next FixedUpdate e in the next Update (which gets called after FixedUpdate) as described here.

    So:
    • FixedUpdate
      • Add Misc Forces
      • Decide Rigidbody2D needs to stop (flag it in script)
    • Update
      • Does script flag a stop is required?
      • Yes, so set Rigidbody2D velocity to zero.
    ... or ...
    • FixedUpdate
      • First, does script flag a stop is required from last update?
      • Yes, so set Rigidbody2D velocity to zero.

      • Add Misc Forces
      • Decide Rigidbody2D needs to stop (flag it in script)
     
    akingdom likes this.
  6. JymWythawhy

    JymWythawhy

    Joined:
    Jan 18, 2015
    Posts:
    25
    Thanks for your help! Adding a "Stopped" bool (and a coroutine to unstop it after a frame or two) and a "If stopped" statement in update that sets the velocity to zero did the trick. Now my virtual spaceship stops on a dime.