I am writing a script in unity that applies a force to the object to advance it a set distance in an environment without friction or drag, producing a cosine force curve.
However, as the target approaches the destination, the force to apply is less than the value specified by the curve as the time unit is too large and will cause the object to reverse direction.
To resolve this, I estimate what the speed will be after applying this frames force and, if that reverses the direction, we take a proportion of the force.
It is working well around 4 times out of 5, but every so often it will not detect the reverse in direction and will apply the force for an extra frame or 2, causing the object to back up.
Closer investigation revealed that basically the problem stems from my estimate being significantly (some times up to 0.05) different from the velocity the next frame. I compute it as follows:
Vector3 currentVelocity = ship.rigidbody.velocity; Vector3 direction = ship.transform.right; // this is the value I use for the "actual" speed float velocityAlongDir = Vector3.Dot(currentVelocity, direction); // this is my estimate float estimatedVelocity = velocityAlongDir + (applyingForce * lDeltaTime);
applyingForce is applied thus:
ship.rigidbody.AddForce((applyingForce * ship.rigidbody.mass) * transform.right);
Some sample data:
Predicted velocity: 0.3048308 Actual velocity: 0.2880591 Predicted velocity: 0.2068605 Actual velocity: 0.1900333 Predicted velocity: 0.09798826 Actual velocity: 0.1900333 Predicted velocity: 0.1082982 Actual velocity: -0.007007703
As you can see by the last entry, the predicted value doesn't change sing, but the real value does. Trying to work around this using does it go below a small value get different problems where the current velocity is too small etc.
Any idea why my calculation for next frame velocity seems so wrong and is there anything I can do about it?
As pointed out in the comments, I needed to apply the force in the
FixedUpdate and calculate my next frames velocity using
Time.fixedDeltaTime. However, the following can happen, presumably in adverse frame conditions:
Predicted Velocity: 15.67547 Actual Velocity: 15.67547 Predicted Velocity: 17.54726 Actual Velocity: 15.67547 // note the same as the previous update, there has been no physics step! Predicted Velocity: 17.51759 // estimate is subtly different, because my own timer has advanced
I fixed this by using
fixedTime as opposed to
fixedDeltaTime. However, then when I do a double update I am wrong for that frame, its like the physics step is trying to make up for the lost time:
// all going well... Predicted Velocity: 52.25977 Actual Velocity: 52.25977 Predicted Velocity: 52.40138 // the estimate is wrong, we are moving at the same speed => no physics update Actual Velocity: 52.25977 // we predict the same velocity for next frame Predicted Velocity: 52.40138 // but we are wrong, like it is trying to catch up for lost time Actual Velocity: 52.543 // then after that point we are precisely right Predicted Velocity: 52.66479 Actual Velocity: 52.66479
This wouldn't be an issue except in the edge case where we do this double step precisely at the point we need to detect when the speed will change and apply the ratio. Since the physics step seems to play catch up, I miss the fact we changed speed.