# Find the direction a Projectile should be fired from a Moving Object to hit another moving Object?

I am trying to do a simple AI Controller, which fires Missiles at the surrounding targets in the Scene.

• The AI Controller can fire projectiles when moving or stationary.
• The Targets are either stationary or move around in the scene with a Constant Velocity and can't fire projectiles.

I did some searching on Stack overflow and came up with this code to find the direction the AI controller must fire the projectile (constant speed) to hit a target travelling at a constant velocity(it can also be stationary):

private bool GetProjectileDirection(GObject target, GObject source, out Vector3 direction)
{
// Initialize direction to Zero
direction = Vector3.zero;

// The Relative Position between the AI Controller and the target.
Vector2 w = new Vector2(target.Position.x - source.Position.x, target.Position.y - source.Position.y);

// The Relative Velocity between the source and the target.
Vector2 v = new Vector2(target.Velocity.x - source.Velocity.x, target.Velocity.y - source.Velocity.y);

float a = Vector2.Dot(v, v) - BULLET_SPEED * BULLET_SPEED;
float b = Vector2.Dot(w, v);
float c = Vector2.Dot(w, w);

float root = (b * b) - (a * c);

// The Problem seems to occur here as this becomes less than zero most of the time,
// and exits the function.
// But on the screen, the object is well within the range for the AI to fire at it
if (root < 0)
return false;

// If root < 0, then this becomes NaN and brings the simulation to a crawl
double t = (-b - Math.Sqrt(root)) / a;

double shootX = w.x + t * v.x;
double shootY = w.y + t * v.y;

double theta = Math.Atan2(shootY, shootX);
direction = BULLET_SPEED * new Vector3(Math.Cos(theta), 0, Math.Sin(theta));

return true;
}


I am pretty sure I am missing something. I just can't pinpoint what exactly is it. As a result, the AI seems to miss most of the targets around it.

• Looks like you may have forgotten to add the launcher's velocity to its projectile on firing. – DMGregory Sep 22 '19 at 12:30
• @DMGregory But most of the time the Execution doesn't even reach the part of the Code. The code returns at the line if(root < 0). – Vignesh Gunasekaran Sep 22 '19 at 12:34
• That usually means your bullet speed is too low. We can check the math though to see if there's an error in the formula. – DMGregory Sep 22 '19 at 12:36
• Okay! Let me check! – Vignesh Gunasekaran Sep 22 '19 at 12:36
• @DMGregory Okay! You were right. Increasing the Bullet speed resulted in the Projectiles being fired! But the Accuracy is all over the place! – Vignesh Gunasekaran Sep 22 '19 at 12:41

This is the updated code, with code for handling some edge cases. Also, I made sure the BULLET_SPEED large enough for the Equations to work:

 private bool GetProjectileDirection(GObject target, GObject source, out Vector3 direction)
{
direction = Vector3.Zero;

Vector2 w = new Vector2(target.Position.x - source.Position.x, target.Position.y - source.Position.y);
float ww = Vector2.Dot(w, w);

Vector2 v = new Vector2(target.Velocity.x - source.Velocity.x, target.Velocity.z - source.Velocity.z);

double a = Vector2.Dot(v, v) - (BULLET_SPEED * BULLET_SPEED);
double b = 2 * Vector2.Dot(w, v);
double c = Vector2.Dot(w, w);

double h = -b / (2 * a);
double k2 = h * h - (c / a);

double t = 0.0f;

if (k2 < 0)
return false;

if (k2 == 0)
{
if (h > 0)
t = h;
else
return false;
}

if (k2 > 0)
{
double k = Math.Sqrt(k2);
double r0 = h - k;
double r1 = h + k;

if (r0 > 0)
t = r0;

else if (r1 > 0)
t = r1;

else
return false;
}

double shootX = w.x + t * v.x;
double shootY = w.y + t * v.y;

double theta = Math.Atan2(shootY, shootX);
direction = new Vector3(Math.Cos(theta), 0, Math.Sin(theta));

return true;

}


Here is the answer that I based this code off.