- Home /
Reducing rounding errors in my physics solvers
It's the age old game physics question: I want to set the velocity of a rigidbody2D so that it will start at a position, fly along a certain trajectory and arrive at a set final position. I set out with a pad and pencil, did the physics work and came up with a set of equations to give me the initial velocity.
However, when I wrote code for these equations: the projectile misses by a fraction of a unit. I suspect that this is because of floating point errors inherit in the order that I have the operations in my method.
public class Throw : MonoBehaviour
{
public float XDisplacement = 5.0f;
public float YDisplacement = 4.0f;
public float Apogee = 10.0f;
// Use this for initialization
void Start ()
{
var gravity = Physics2D.gravity.magnitude * rigidbody2D.gravityScale;
var velocity = rigidbody2D.velocity;
velocity.y = Mathf.Sqrt (2 * gravity * (Apogee - YDisplacement));
var arrivalTime = Mathf.Sqrt (2 * YDisplacement / gravity + 0.5f * Mathf.Pow (velocity.y / gravity, 2)) + velocity.y / gravity;
velocity.x = XDisplacement / arrivalTime;
rigidbody2D.isKinematic = false;
rigidbody2D.velocity = velocity;
}
}
My suspicions were confirmed when I changed the method to be algebraically equivalent and got slightly worse results.
What I have tried so far: Setting var squaredYVelocity = 2 gravity (Apogee - YDisplacement); and then velocity.y = Mathf.Sqrt (squaredYVelocity); and using squaredYVelocity in the calculation of arrivalTime instead of re-squaring velocity.y
Moving the 0.5f coefficient around and instead multiplying gravity by two
Setting isKinematic to true in the editor in case the projectile is dropping slightly before Start() is called (It's not)
All of the other questions that relate to this area use angles to direct their projectiles and thus end up having to calculate arcsines, I find this silly when all that's important to me is the apogee, displacement of x and the arrival time.
I realized after writing my physics equations that the X and Y displacements should represent a vector2 from the origin to the target, but that's just not how I was thinking at the time.