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.

Can you paste a link to the script in the wiki?

1 Answer

1

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:

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
}

Bleh.. there's some pretty sexy linear algebra going on. Are you familiar with the discipline?

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).

It took me 2h of walking circles and thinking to understand the math and picture the lines in my brain. Also I had to read what Dot() does. ;) Never got into advanced math at School. There are good, free math libraries for unity, also for interception. http://wiki.unity3d.com/index.php/3d_Math_functions cheers

Wow, @Vicarian can you upload it? That's unbelievable; that was quick