# Calculating Lead For Projectiles

m (Split very long comment line) |
|||

Line 22: | Line 22: | ||

targetPosition = targetPosition + targetQ * relativeTimeToTarget(selfPosition, selfQ, targetPosition, targetQ, projectileSpeed); | targetPosition = targetPosition + targetQ * relativeTimeToTarget(selfPosition, selfQ, targetPosition, targetQ, projectileSpeed); | ||

− | // from here on in you assume that by the time your projectile collides with the target the target will be at the location stored in targetPosition! | + | // from here on in you assume that by the time your projectile collides with |

+ | // the target, the target will be at the location stored in targetPosition! | ||

// ... your tracking/movement code here | // ... your tracking/movement code here |

## Revision as of 12:37, 23 November 2007

Since this is a snippet this isn't a cut and paste job. It's meant as a pointer so you can integrate this easily into your own code. All the examples are in C#.

These script fragments allow you to add some lead ahead of the target allowing projectiles/missiles to collide with the target - A quadratic rather than an iterative solution.

## Aiming Code

<csharp>

// how fast the projectile will go (this might be the magnitude of targetQ also) float projectileSpeed = 40;

// aliases for where we are Vector3 selfPosition = transform.position; Vector3 targetPosition = target.transform.position;

// aliases for where we are going Vector3 targetQ = (target.rigidbody!=null) ? target.rigidbody.velocity : Vector3.zero; Vector3 selfQ = (rigidbody!=null) ? rigidbody.velocity : Vector3.zero;

// assuming that the projectile moves, and the target is moving add some lead to the target if(targetQ.sqrMagnitude !=0 && projectileSpeed > 0)

targetPosition = targetPosition + targetQ * relativeTimeToTarget(selfPosition, selfQ, targetPosition, targetQ, projectileSpeed);

// from here on in you assume that by the time your projectile collides with // the target, the target will be at the location stored in targetPosition!

// ... your tracking/movement code here </csharp>

## Calculating the time to target

Here's the rocket science bit. But actually it isn't. I shan't bore you with the details, but a solution to the same problem is [here] which takes you through a thorough description of the problem, but solved in a rather more complex manner.

<csharp>

// if we're moving, and they're moving we need to and origin isn't at 0,0,0 we need to use the difference // of "this" and "target" position/velocities

public static float relativeTimeToTarget(

Vector3 originPosn, Vector3 originVel, Vector3 targetPosn, Vector3 targetVel, float pVel)

{

Vector3 diffPosn = originPosn - targetPosn; Vector3 diffVel = originVel - targetVel ; if(targetVel.sqrMagnitude == 0) diffVel =originVel; return timeToTarget(diffPosn, diffVel,pVel);

}

// This is the meat of the code - the quadratic solver // and to think you thought this was rocket science! Solved by high school maths! // thanks to Ed (idevgames) for the original idea, and JohnJ of JJFFE for fixing my lame attempt at 3difying it public static float timeToTarget(Vector3 vTargetPosn, Vector3 vTargetVelocity, float projectileVelocity) {

float a = Vector3.Dot(vTargetVelocity,vTargetVelocity) - (projectileVelocity*projectileVelocity); float b = 2*Vector3.Dot(vTargetPosn, vTargetVelocity); float c = Vector3.Dot(vTargetPosn,vTargetPosn);

float d = b*b - 4*a*c; float t = 0; float u = 0; float tt = 0; float tu = 0; float r = 1; // add one second of lead if we're unsolvable

if (d >= 0) { tt = (-b + Mathf.Sqrt(d)) / (2*a); tu = (-b - Mathf.Sqrt(d)) / (2*a);

// This portion picks the smallest nonnegative root. t = (tt < 0) ? System.Single.PositiveInfinity : tt; u = (tu < 0) ? System.Single.PositiveInfinity : tu;

r = Mathf.Min(t,u); }

return r;

}

</csharp>