A high-precision projectile targeting system that accurately predicts and hits moving targets in Unity. Perfect for tower defense games, and games where AI characters need to fire projectiles at moving enemies.
This system uses advanced ballistic calculations to determine the exact launch angle and velocity needed to intercept moving targets, whether you're launching missiles, arrows, fireballs, grenades, or any other projectile.
Add a MissileLauncher component to your turret or AI GameObject. In the Inspector, assign a
Launch Point transform (the muzzle) and a Missile Prefab — the prefab must have a
Missile component and a Rigidbody. Set Projectile Speed, toggle
Use Gravity to match the prefab's Rigidbody "Use Gravity" setting, and tune
Prediction Iterations (3–4 is usually optimal for missiles with short travel times).
The transform you pass to TryLaunchAtTarget is the exact point projectiles will converge on
and will also be used to find the velocity carrying component. The recommended setup is to add an empty
child object named Target to your enemy, positioned at center mass.
Make the Target a child of the object that has the movement component — a
NavMeshAgent, CharacterController, or Rigidbody. The solver reads
the target's velocity by searching upward from the aim point through its parents, checking for those
components in that order. Deeper nesting under the moving object also works — for example, attaching the
aim point to an animated bone so it follows the animation. If no movement component is found above the
aim point, the target is treated as stationary.
Call TryLaunchAtTarget whenever you want to fire. It reads the launcher's Inspector settings, computes the firing solution, and spawns/launches the missile in one call:
public class Turret : MonoBehaviour
{
private MissileLauncher missileLauncher;
public Transform targetPoint; // the enemy's "Target" child (see Setting Up Targets)
void Start()
{
missileLauncher = GetComponent<MissileLauncher>();
}
void Fire()
{
bool success = missileLauncher.TryLaunchAtTarget(targetPoint);
if (!success)
{
// Target out of range, or missile prefab is missing a Missile component
}
}
}