Sunday 1 August 2021

My Home Game Engine - Motion Decay (Physics) Bug

A few of you may have noted I've been writing my own graphics engine at home, this has fast become my own home game engine; which is more or less just a play ground for me play about with.

And over the weekend I've started to flesh out the physics engine, beginning with a physically reactive camera.  I want to make this thing tilt and shake and move like it's organic, not on the end of your keyboard or mouse.

The motif is going well.

I designed a head for many edge cases I expected, one of them being floating point in accuracy and so I built two things into the movement, first a dead-zone, so zero isn't the ONLY value which doesn't move the camera, instead an area of 0.0004 around the camera forms a null - don't move - zone for all my motion calculations.

And the second was the force of friction or wind resistance, this is just called "Decay" in my engine, you decay from moving to  no longer moving.  Because wind, water or surface friction are going to come into play at different times and from different directions on each object.

Anyway, do work out the motion which needs applying to any object I build a vector of motion actions, these themselves are stored in a set of efficient constexpr static arrays per object type; for not I have so few object types this is fine, it leads to faster code (one day, if I have more than ten moving object types I may need to revisit this.

Alas, this smartness immediately bit me in the arse... And I just spent nearly half an hour pawing over the wrong piece of code to figure out why when switching to an object known to be at rest (0, 0, 0) with no actions on it... it'd slowly jiggle backwards at a very slow rate.

I checked my maths, my direction vectors, my initialization of the actual speed of the object, everything checked out.  I made sure I was giving no inputs, so I wasn't landing in the accelerate or decelerate motion actions.

So I was properly confused, I took a moment and I re-read the code I'd done yesterday (oh the difference a day makes) and suddenly I realized I had two kinds of decay... if you're moving forward you slow down... and if you're moving backwards you also slow down... both heading to zero, or at least the 0.0004 null zone.

Other objects were not moving, just this one particular type... and having a quick squizz, sure enough the acceleration and deceleration decay were BOTH being applied, even at rest this object would jump to a speed and start to decay, this would then swing it below -0.0004 in the null zone and the deceleration decay would kick in... and the deceleration was MORE than the acceleration so then the object was trying to decelerate a little but more each third frame... zero to backwards to null zone to backwards to nullzone... on and on, tiny increments.

This was a flat out bug, the decay should have only been applied to make the object come to, but not beyond the nullzone.

However, I was still perplexed how the forward decay was being applied, sure enough it is, in the above call to "GetMotionActions" we can see it's both ForwardSpeedDecay and BackwardSpeedDecay are "valid" motion actions for objects receiving no input.

And they'd been doing this all the time, every frame... the specialty of this one particular object?  Just the numbers, the profile for motion, specifically the braking, was a larger number taking it beyond nullzone.  And this is multipled by delta time for the frame... all following frames are small, short, but the first frame?... or a frame after a break point... HUGE....

In short I made a bunch of mistakes, but I learned, and I enjoyed myself.  This is perhaps the key thing when trying something new.

I also have a healthy appreciation for just taking a physics engine off of the shelf having done some of this ground work - and I'm literally just playing.

No comments:

Post a Comment