Yearly reminder to not do gravity (and all acceleration) wrong in your games!

edited in General
Got this link off Twitter:

http://www.niksula.hut.fi/~hkankaan/Homepages/gravity.html

This is the best description of this problem, and the most graphic representation of the symptoms I've ever seen. Everyone should know about this mathematical snafu :)

Comments

  • While I agree with his point, I do think that his math is not quite 100%. You can't just replace dt with a period of time and shuffle around the pieces - that's not how calculus works. Mostly just a quibble, but an important one I feel.

    Also, this issue extends far beyond just jumping (he does point this out, but he doesn't really elaborate). For instance, you don't want to be able to fall through a platform if you are moving too fast. Also, he only deals with constant acceleration, which is common is games, but not always the case.

    Hopefully my nit-picking doesn't negate the message. Everyone doing game dev should be aware of this if they aren't already.
  • Well, it isn't a calculus solution, however calculus proves he is correct. It has more to do with minimising the error accumulated between frames, and in this correction it translates into not losing accuracy when the fps drops.

    If you took used:
    velocity = velocity + gravity*delta_time
    position = position + velocity*delta_time

    as the divisions got smaller, you would expect the amount the player character has moved (absolute distance) would get closer and closer to the actual curve (as it gets closer and closer to being the same as the integrated form). However you need to take into account rounding error, any decimal value you use introduces rounding error, especially in computing when using small values (there are a number of reasons, and many languages have their own methods of dealing with rounding error however the accuracy of these are far from ideal), the smaller dt gets, the larger the error gets, and thats why a higher fps with the first algorithm would be less accurate (nevermind the lower fps having the possibility to not jump at all). So if you accumulate the dt over time you will find it deviates from the correct value (and the is more apparent with smaller dt values).

    By using half of the dt change immediately and half the next update cycle you are forcing the game to "average out" the dt change (barely the right way to describe it, but thats the best way I could describe it) which means as you decrease dt substantially it becomes more accurate (you get less rounding error for both the current "dt" change and the next one). And the rounding could go either way for half "dt0" + half "dt1" which on average will be closer to the actual value. So it would over time be closer to the correct value for accumulated dt.

    What I am trying to point out is how we combat the rounding errors to try and accumulate the correct game time over extended periods of play (which in turn makes gravity/jumping/moving much smoother and feel more uniform), it isn't that the methods are "wrong", it is just that you can pick the one that is "more accurate" from a computation perspective.

    Wikipedia explains the rounding errors well.

    Though, error correction in computation is its own complicated field, and I dont think I did a good job trying to explain what I meant in this post either...
  • @francoisvn: I don't understand your gripe. He's not replacing dt with a period of time, he's simply moving the velocity sampling point away from the edge of the dt envelope. I would have thought that the graphs made it pretty clear that the common equations over-applied acceleration as dt grew larger. This is a fix for that. You could easily apply the same logic to sampling your acceleration over time if that changed similarly.

    Also, falling through platforms is a completely different problem and has absolutely nothing to do with these sets of equations, I'm not sure why you're bringing it up. Sweep collision detection is what you're after in that case :)

    @edg3: I'm not sure the issue with the first set of equations is accumulation of rounding errors - the second set actually introduces more rounding problems through the division, although with small floats that's less of a problem. As I said above, it's more about Euler's method over-estimating total force over time ;)
  • My only issue was with his explanation in the final paragraph. However, I re-read it now and I see I misread the first time, I thought he was just shuffling around the calculus pieces, which is not always sound math. I wasn't disagreeing with anything else in that document.

    I see falling through platforms as a related problem. It is a problem that occurs when you break up a continuous process into a discrete process and forget about some of the important details. But I can see why you would say it isn't related.
  • velocity = velocity + gravity*delta_time * .5
    position = position + velocity*delta_time
    velocity = velocity + gravity*delta_time * .5


    :P
  • Damn you! Now I have to fix my game
  • Don't worry about the smoke you are smelling thats just my brain melting, how is it I get the math when I look at the formula but most of the time the explanation confuses the heck of me.

    PS. Thanks for posting the link helps me out.
  • This looks very good, and I really wish I understood why the /2 makes ALL the difference...
  • I never thought I'd say it but I miss mathematics. And Euler and his methods gave headaches on the regular :)
Sign In or Register to comment.