I’m predicting where a GameObject’s transform.forward will be in X number of FixedUpdate() calls.
I got it 100% accurate when the Rigidbody’s angular drag is 0 but if it’s for example the default 0.05 I get somewhat close accuracy but not 100% correct. The error also gets larger the further into the future I’m trying to predict where the transform.forward will be.
Here is how I reduce the angular velocity of the Rigidbody right now:
However it seems like this isn’t exactly how PhysX is applying the angular drag (or angular damping as they call it).
So my question is what is their calculation formula? (In programmer terms, please.)
I know that angular drag is the problem because if I set it to 0 I get correct predictions no matter how far into the future I try to predict. I’m also aware of the workaround of setting angular drag to 0 on the Rigidbody and then applying angular drag myself in the FixedUpdate() but I don’t want to have to modify the Physics only to predict them…
I’m willing to accept a non-accurate prediction just as long as I know I’m using the same calculations that PhysX is using (errors due to float rounding limitations etc is fine). I’ve searched around a lot and can’t find them… Just the code above (from non-official sources) and it doesn’t give accurate results so I’m guessing it’s just someone’s guess on a forum.
Simple as that. Notice that if your Rigidbody has a angular drag higher than or equal to the number of FixedUpdate() calls per second in your game the Rigidbody will always stop spinning immediately (rigidbodyAngularDrag becomes 1 or greater).
Now, I’m not completely sure if this really is PhysX/Unity’s way of applying angular dampening but it’s what I get closest results with even when predicting 30 seconds into the future. The prediction is not 100% but it’s close enough for me to believe that float limitations or other stuff that can’t really be controlled is the cause of the mismatch. It also makes sense for the physics engine to avoid expensive Mathf.Pow() calls so yeah, this is probably a wrap folks.
Please post if you have anything else to add, especially corrections. I’ve already noticed that this thread comes up when searching the net for “how does unity apply angular drag to gameobjects” or similar so it’d be nice to put as much info on the subject as possible here.
I don’t know what physx is doing internally, but normally I do this for drag-like behaviour in my own code:
velocity *= Mathf.Exp(-drag * Time.deltaTime);
Time.deltaTime is anyway fixed in this case, but this works better than your approach for varying frame rates (but there’s still some precision error compared to analytic solving).
This is assuming you use the code in FixedUpdate, where Time.deltaTime is equals Time.fixedDeltaTime. The “exp” formula results stay more predictable when changing the physics time step (eg. during development). It’s not meant to work for real varying frame rates like in Update().
This would be the same code, with unambiguous deltaTime and more context:
I was just saying that Time.deltaTime is never equal to Time.fixedDeltaTime, not even if you use it in FixedUpdate…
Maybe the language barrier is messing what you’re trying to say.
From Unity documentation, FixedUpdate is executed approximately 1/fixedTimeStep amount of times per seconds, that means, your fixed update can be called twice before another update loop is called, but fixed update will execute the amount of times needed per second, but isn’t fixed to work in correlation with update loop.
Assuming that X will remain constant. Could you not just do an example run and get a value of where the fwd is at that X time. Then create an empty game object, make it a child of your parent and point it at the final X orientation of where fwd was pointing. Then when you need to predict where fwd will be just query where the empty game object is pointing. Not sure if that would satisfy your requirement.