I'm trying to get my turrets to lead their targets by roughly predicting where the enemy will be X seconds from where they are now (X being the time it takes the projectile to fire that far).
I have the current target position, the flight time of the projectile and the velocity of the rigidbody. How do I mix these together to get back a position X seconds in the future?
The simplest thing you could do is simply takes its velocity and add that to your object. You can make a more advanced prediction based on how much control you have over its movement or if you can determine when it will hit an obstacle.
This script simply adds the velocity to its current position:
var secondsInAdvance : float;
var framesInAdvance : int;
var useFrameCounter : Boolean;
function CalcFuturePos () : Vector3 {
var finalPos : Vector3 = transform.position;
var velocity = rigidbody.velocity;
if(useFrameCounter) {
velocity *= Time.deltaTime;
velocity *= framesInAdvance;
finalPos += velocity;
}
else {
velocity *= secondsInAdvance;
finalPos += velocity;
}
return finalPos;
}
Now of course this is about as basic as you can make it. It just calculates the future position of an object by adding its current velocity. It doesn't account for acceleration, direction change, or collisions.
If anyone is looking for a solution that factors in drag, this is the formula I’ve found to work almost perfectly for predicting the position of a rigidbody over time (until it bounces… still trying to figure out how to emulate the unity math there…)
for (int i = 0; i < TRAJECTORY_FRAMES; ++i)
{
velocity *= (1.0f - Time.fixedDeltaTime * rigidbody.drag); // drag
velocity += Physics2D.gravity * rigidbody.gravityScale * Time.fixedDeltaTime; // gravity
position += velocity * Time.fixedDeltaTime; // move point
// Plot the predicted point visually
this.LineRenderer.SetPosition(i, position);
}
Even if this is kinda old, it might be useful to post here a function that takes an expected time as an argument.
It is basically working on the same concept as above.
Taking a look at This Question might also help.
public Vector2 FuturePosition(float time)
{
// Programming Game AI by Example - Mat Buckland
// https://answers.unity.com/questions/1087568/3d-trajectory-prediction.html
// Starting position of the ball
Vector2 pPos = BallRigidbody.position;
// Drag multiplier (friction)
float rDrag = Mathf.Clamp01(1.0f - (BallRigidbody.drag * Time.fixedDeltaTime));
// How much velocity is added per frame
Vector2 velocityPerFrame = BallRigidbody.velocity;
// How many frames are going to pass in the given time
for(int i = 0; i < time/Time.fixedDeltaTime; i++)
{
velocityPerFrame *= rDrag;
pPos += (velocityPerFrame * Time.fixedDeltaTime);
}
return pPos;
}