# Sniper aim prediction

I'm trying to make a sniper aim prediction for an Unreal Engine 4 game. I've found this interesting question Projectile Aim Prediction with Acceleration, and I tried to implement in C++ what DMGregory said. The result I got isn't bad at all, but I've some doubts about something in his explanation. First, what does he mean with v_T? Should I calculate it as

FVector v_T = targetVelocity - myVelocity;

or as

FVector v_T = targetVelocity - myPosition;?

The vectors myVelocity and myPosition are respectively the velocity and the position of the shooter (me).

Then, I noticed that the sniper projectile trajectory doesn't seem to be a perfect parabola, so I avoided the v_p calculation, and I've simply calculated the predicted target position as

FVector predictedTargetPosition = targetPosition + targetVelocity * deltaTime + targetAcceleration * deltaTime * deltaTime * .5f;


where the 3 vectors targetPosition, targetVelocity and targetAcceleration are relative to the game world axis.
After that, I simply added to the Z component of the predictedTargetPosition the following amount:

recalculatedTargetPosition.Z += fabs(bulletAcceleration.Z) * deltaTime * deltaTime * .5f;


in order to compensate the loss of height of the projectile in time.

What do you think about it?

• Why not ask the one who wrote the question? He's still very active – Bálint Oct 28 '17 at 10:37
• Subtracting a position from a velocity doesn't mke much sense... – Quentin Oct 28 '17 at 10:55
• Thanks. In fact I used targetVelocity - myVelocity for the calculation. – Saint Santo Oct 28 '17 at 11:09
• If your bullet is so fast that your shooter and target are scarcely moving by comparison - typical in a sniper scenario - you might not want to use the full complexity of that answer and instead treat everything but the bullet as stationary. The math for this case is simpler – DMGregory Oct 28 '17 at 12:47

First, as noted in the comments, it's not geometrically or physically meaningful to subtract a position from a velocity. So we start by computing the relative velocity like so:

relativeTargetVelocity = targetVelocity - myVelocity;


Then we can proceed through the steps of the other answer like so...

// See linked answer for the full derivation of this math.
timeToImpact = SolveForImpactTime(
relativeTargetPosition,
relativeTargetVelocity,
targetAcceleration,
projectileSpeed,
projectileAcceleration );

relativeImpactPoint =  relativeTargetPosition
+ relativeTargetVelocity * timeToImpact;
+ targetAcceleration * timeToImpact * timeToImpact * 0.5f;


Let's introduce your "recalculated target position" with a slightly tweaked notation:

pointAboveImpact = relativeImpactPoint
- projectileAcceleration * timeToImpact * timeToImpact * 0.5f;


If we want to fire the projectile along the line to this point in the shooter's relative coordinates, we can form the projectile's initial velocity by dividing this offset by time. Let's manipulate that a bit...

relativeLaunchVelocity = pointAboveImpact / timeToImpact

= (relativeImpactPoint
- projectileAcceleration * timeToImpact * timeToImpact * 0.5f) / timeToImpact;
// Distributing the division through....
= relativeImpactPoint / timeToImpact - projectileAcceleration * timeToImpact * 0.5f;


Which is exactly the formula from the original answer:

  v_p = travel / t - (a_p/2.0) * t


So you haven't changed the underlying math here, just written the steps differently.

Remember that this launch velocity is still in the shooter's inertial frame, so if the shooter is moving, don't neglect to add the shooter's velocity to get the projectile velocity in the world frame of reference.

If you're finding your predicted velocity is not giving the desired results, you'll need to include explicit error cases so we can diagnose the problem.

• First of all, thanks for your reply. Basically, in my case, I just need a point (relative to the game world frame) at which to aim. So, once I calculate the pointAboveImpact, I have all what I need. I've just to add myPosition to it in order to have this point relative to the world frame, right? – Saint Santo Oct 28 '17 at 13:51
• Right. Or you can just take the direction of the launch velocity. – DMGregory Oct 28 '17 at 13:53
• I tried, for curiosity, both approaches. While the pointAboveImpact + myPosition gives what I expected, the relativeLaunchVelocity + myVelocity doesn't. I can't understand the reason of this. – Saint Santo Oct 28 '17 at 14:04
• We would not expect those two to be directly interchangeable. You're not trying to use the velocity as a point, are you? Add myPosition to convert the velocity into a position one unit of time in the future along a straight line. – DMGregory Oct 28 '17 at 14:05
• Yes, in fact if I do this -> relativeLaunchVelocity + myPosition, it works. But I thought it was wrong. – Saint Santo Oct 28 '17 at 14:08