# Predic future position of enemy and where bullet will be to hit 100% of the time.

Here is a screenshot of what I’m trying to accomplish:

I do not want to use the built in unity movetowards or anything like that. this is a pure c# formula question. How would I detect this without using help from unity. The reason why is because unity turns the bullets with movetowards which is not what I want…the bullet needs to remain straight and impact the target’s position it’s moving towards.

It is a prediction formula I’m looking for and it’s pretty basic but I’m so use to just cheating and using stuff like vector3.movetowards that I’m not really sure how to do this.

What I’ve figured out so far is I will need to do something like this…

``````Vector3 newTargetPos = targetObject.Position* targetObject.Velocity;
Vector3 newPlayerPos = player.Position* player.Velocity;
``````

and then shoot with newTargetPos + newPlayerPos

but what’s the rest of the formula? how do I do the rest? bulletspeed would be used somehow in this right?

1 Like

You’re mixing up an algorithm to move an object in a straight line, versus an algorithm to calculate where 2 lines would intersect.

If you want the second, well you need to start with what unknown variable are you calculating for, and what values are known and/or constants.

For example, the thing you’re trying to shoot is moving from some position in some direction and some speed. These are knowns that can’t be changed.

The projectile you shoot is probably also a constant, and therefore known.

Where as the position you shoot from, the speed you can move to that position at, the time you shoot at, and the direction you shoot in are all unknowns.

And the thing is, the more unknowns, the harder it is to calculate, since there can be an infinite number of answers to resolve a system with 2 or more unknowns. So usually you calculate with 1 unknown… just like a sniper will lay down and not move and reduce all unknowns (wind velocity, etc) and then just shoot in a specific direction (1 variable) to increase accuracy of strike.

Well you need to do the same thing. You need to decide what unknowns you’ll force to knowns (stop moving and stand still to shoot), to reduce unknowns to 1 or 2.

And even then there’s no guarantee. You could stop movement and end up behind a wall, and therefore unable to shoot.

for the target the knowns are:
velocity & position
projectile knowns are:
speed
player knowns are:
velocity & position
so your saying I would have to do to many calculations with this much information and there is no real simple way to do it?
Walls would not matter in this equation btw that whole thing can be ignored.
Think of it as an automated targeting asteroids game.

I have converted the information james has given as follows:

``````static float sqrMagnitude(Vector3 v3)
{
float temp = (float)Math.Sqrt(v3.X * v3.X + v3.Y * v3.Y + v3.Z * v3.Z);
return temp;
}

static float magnitude(Vector3 v3)
{
float temp = v3.X * v3.X + v3.Y * v3.Y + v3.Z * v3.Z;
return temp;
}

//first-order intercept using absolute target position
public static Vector3 FirstOrderIntercept
(
Vector3 shooterPosition,
Vector3 shooterVelocity,
float shotSpeed,
Vector3 targetPosition,
Vector3 targetVelocity
)
{
Vector3 targetRelativePosition = targetPosition - shooterPosition;
Vector3 targetRelativeVelocity = targetVelocity - shooterVelocity;
float t = FirstOrderInterceptTime
(
shotSpeed,
targetRelativePosition,
targetRelativeVelocity
);
return targetPosition + t * (targetRelativeVelocity);
}
//first-order intercept using relative target position
public static float FirstOrderInterceptTime
(
float shotSpeed,
Vector3 targetRelativePosition,
Vector3 targetRelativeVelocity
)
{
float velocitySquared = magnitude(targetRelativeVelocity);
if (velocitySquared < 0.001f)
return 0f;

float a = velocitySquared - shotSpeed * shotSpeed;

//handle similar velocities
if (Math.Abs(a) < 0.001f)
{
float t = -magnitude(targetRelativePosition) /
(
2f * Vector3.Dot
(
targetRelativeVelocity,
targetRelativePosition
)
);
return Math.Max(t, 0f); //don't shoot back in time
}

float b = 2f * Vector3.Dot(targetRelativeVelocity, targetRelativePosition);
float c = magnitude(targetRelativePosition);
float determinant = b * b - 4f * a * c;

if (determinant > 0f)
{ //determinant > 0; two intercept paths (most common)
float t1 = (-b + (float)Math.Sqrt(determinant)) / (2f * a),
t2 = (-b - (float)Math.Sqrt(determinant)) / (2f * a);
if (t1 > 0f)
{
if (t2 > 0f)
return Math.Min(t1, t2); //both are positive
else
return t1; //only t1 is positive
}
else
return Math.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 Math.Max(-b / (2f * a), 0f); //don't shoot back in time
}
``````

However I’m not sure how unity does sqrmagnitude I think it’s wrong because it is only semi working.

magnitude is:

sqrt(x^2 + y^2 + z^2)

sqrMagnitude is just the same thing with out the sqrt, because sqrt is expensive.

x^2 + y^2 + z^2

ah so I wrote them backwards lol ok easy enough fixed these 2:

``````static float sqrMagnitude(Vector3 v3)
{
float temp = (float)(Math.Pow(v3.X, 2) + Math.Pow(v3.Y, 2) + Math.Pow(v3.Z, 2));
return temp;
}

static float magnitude(Vector3 v3)
{
float temp = (float)Math.Sqrt(Math.Pow(v3.X, 2) + Math.Pow(v3.Y, 2) + Math.Pow(v3.Z, 2));
return temp;
}
``````

However this is just a performance change more then anything good change though!

EDIT: fixed the power calculation

It does work while standing still now! but when moving something is being calculated wrong

You need to account for bullet drop as well.

Angle of Reach is what you need to add. Calculates how far above a target to aim

There is no arc’s or bullet drop so trajectory shouldn’t need to apply does it?

trajectory still applies, it’s just linear instead of curved.

Trajectory is just the path of a moving projectile through space. Your projectile just doesn’t have gravity effecting it.

Ah I’ve always thought of trajectory as gravity being involved guess I’ll look into it. Thing is, it does work if the ship stays still now which makes me think it is just an issue with that interception math when the player is moving.

EDIT: after just reading the very start of what james posted:
"the ballistic trajectory of a projectile is the path that a thrown or launched projectile or missile will take under the action of gravity"
it does involve gravity if you go into trajectory?

Ok. So I assumed that you are using a rigidbody driven projectile. Instantiate, AddForce in correct direction, let it fly. Is this correct? Or are you doing your projectile movement some other way?

The first algorithm doesn’t care about gravity. Its solely about predicting a future position based on projectile velocity and target velocity. It is accurate assuming the target follows a constant vector/speed (straight line). If the target is say flying in a circle, it will likely miss. Not much you can do about that.

The second algorithm is what accounts for bullet drop. It will calculate how much additional angle you need to add based on gravity, velocity, and distance. If your projectiles are not using gravity, you wont need this.

Also make sure your projectile drag settings are 0. Any drag will change the velocity making your projectiles miss. You can account for that with extra algorithms, but tbh, its not worth the effort/calculate. Just turn off drag. Make your life easy.

nah It shoots in a direction based on this vector3. y is not used since it’s 2d.

The easiest way I can think of to describe this is if you want AI to try and shoot ahead of you if you try to strafe left or right. The AI needs to predict where you are moving and how far ahead they predict essentially determines the AI’s accuracy.

What you are talking about is impossible. You cant hit an unpredictable target. If the player moves left/right constantly with no consistency there is no way of accurately predicting where the player will be.

What sort of distances are we talking about? If its 2d, you can probably get rid of the prediction and use angle of reach solely if the distances are close (less than 100 units). This is dependent on the velocity of your projectile. If its slow, you have no chance of prediction.

Also, how are you moving your player?