- Home /
How to calculate the point of intercept in 3D space
So I have been wracking my brain trying to figure this out. So I need to calculate how far ahead to aim for 1 spaceship to fire and hit another spaceship. I need to know this so when the player targets another ship a targeting bracket shows up where the player needs to fire at that point in time. I know there is a code already written to do this on the wiki, however I am not understanding how it works. I am scripting in JS. Any help with this would be greatly appreciated.
Answer by Bunny83 · Jun 06, 2011 at 05:06 PM
Ok, i don't see your problem... Do you want to understand how it works or how you can use it?
Just copy the code in this section:
http://www.unifycommunity.com/wiki/index.php?title=Calculating_Lead_For_Projectiles#Calculating_the_intercept_point
into a new C-sharp script that is located in Standard Assets. Then you can use the function even in JS.
using UnityEngine;
using System.Collections;
public class Intercept
{
//first-order intercept using absolute target position
public static Vector3 FirstOrderIntercept( Vector3 shooterPosition,
Vector3 shooterVelocity,
float shotSpeed,
Vector3 targetPosition,
Vector3 targetVelocity) {
Vector3 targetRelativeVelocity = targetVelocity - shooterVelocity;
float t = FirstOrderInterceptTime( shotSpeed,
targetPosition - shooterPosition,
targetRelativeVelocity);
return targetPosition + t*(targetRelativeVelocity);
}
//first-order intercept using relative target position
public static float FirstOrderInterceptTime(float shotSpeed,
Vector3 targetRelativePosition,
Vector3 targetRelativeVelocity) {
float velocitySquared = targetRelativeVelocity.sqrMagnitude;
if(velocitySquared < 0.001f)
return 0f;
float a = velocitySquared - shotSpeed*shotSpeed;
//handle similar velocities
if (Mathf.Abs(a) < 0.001f) {
float t = -targetRelativePosition.sqrMagnitude
/(2f*Vector3.Dot( targetRelativeVelocity,
targetRelativePosition));
return Mathf.Max(t, 0f); //don't shoot back in time
}
float b = 2f*Vector3.Dot(targetRelativeVelocity, targetRelativePosition),
c = targetRelativePosition.sqrMagnitude,
determinant = b*b - 4f*a*c;
if (determinant > 0f) { //determinant > 0; two intercept paths (most common)
float t1 = (-b + Mathf.Sqrt(determinant))/(2f*a),
t2 = (-b - Mathf.Sqrt(determinant))/(2f*a);
if (t1 > 0f) {
if (t2 > 0f)
return Mathf.Min(t1, t2); //both are positive
else
return t1; //only t1 is positive
} else
return Mathf.Max(t2, 0f); //don't shoot back in time
} else if (determinant < 0f) //determinant < 0; no intercept path
return 0f;
else //determinant = 0; one intercept path, pretty much never happens
return Mathf.Max(-b/(2f*a), 0f); //don't shoot back in time
}
}
In JS you can use it like this:
// I'll assume that both target and shooter are rigidbodies
var target : Transform;
var shotSpeed : float;
function Update()
{
var interceptionPoint = Intercept.FirstOrderIntercept(transform.position, rigidbody.velocity, shotSpeed, target.position, target.rigidbody.velocity);
// Do what you want
}
I am trying to understand how the math and the code works. I have copied and pasted the code and can get it to work, but it seems to be off somewhere positioning my targeting bracket off by enough to cause problems, so I am trying to understand the code to figure out what is wrong.
Bleh.. there's some pretty sexy linear algebra going on. Are you familiar with the discipline?
I'm relatively familiar with linear algebra and usually am fairly good with math but for some reason i'm not able to look at this code and see it in simple y=mx+b terms here. I am fairly new to unity so I think it might be that the javascript/unity speak is tripping me up with the equations here.
Well, i don't try to explain the math :D but it works great. I think your problem is the shooterVelocity. If your projectile uses a fix world-speed you should pass Vector3.zero as shooterVelocity.
This code assumes that the shotSpeed gets added to your own speed(shooterVelocity).
ah, that might be where the problem was. I would still like to better understand the math so I can fully understand the code im using but I think that might be the issue because the shots were either just before or behind the lead bracket.