So I am making a 2D space combat game, with everything free to move in the x-y plane. I want my enemies to be able to aim ahead of the player, so they can shoot accurately. However, I am having trouble doing this.
The relevant code in the game is:
Vector3 predictedPos = new Vector3();
predictedPos = (Vector3)targetRigid.velocity * Time.fixedDeltaTime + targetTransform.position;
Vector3 pursuitDir = new Vector3();
pursuitDir = predictedPos - gameObject.transform.position; //pursuit direction, predicting where the target will be.
transform.LookAt(predictedPos * leadAmount);
transform.Rotate(new Vector3(0, 90, 0), Space.Self); //corrects the issue with the rotation.
This provides an alright response, but the AI doesnāt lead its target enough, so it is always lagging its shots behind the player. It doesnāt rotate quickly enough. Unfortunately I donāt think thereās a way to change the rotation speed used in transform.LookAt, is there?
So how do I deal with this?
1 Like
So this is a rough guess at how to do it, I think you have forgotten to take into account the speed of the bullet, unless I am mistaken, and the ābulletā always takes 1 frame to reach its target?
float bulletSpeed; //units per second
Vector3 PredictPosition ( Rigidbody2D targetRigid )
{
Vector3 pos = targetRigid.position;
Vector3 dir = targetRigid.velocity;
float dist = (pos-transform.position).magnitude;
return pos + (dist/bulletSpeed)*dir;
}
This will still be somewhat incorrect, as in, itās not the best prediction you can get from the information. The best you can would be based on computing the distance at the expected position, however as the expected position is based on the distance, it becomes a little more complicated. It can be done very easily iteratively, and probably also with some simple maths, but I have just got back from a 2 hour algebra lecture, and I canāt think about maths right now!
Hope that helps 
Scribe
A relatively simple way of performing a prediction that Iāve found was by using:
Vector3 PredictPosition ( Rigidbody2D target )
{
Vector3 velocity = target.velocity;
float time = Vector3.Distance(transform.position,target.transform.position)/(bulletSpeed * Time.smoothDeltaTime);
Vector3 coef = velocity*time;
Vector3 newTarget = target.transform.position + coef;
return newTarget;
}
Hi, I know Iām replying to a 4 year old post but since itās first when I search for AI aiming in Unity, I think itās worth some precision.
This article explains the maths behind the exact prediction incredibly well:
Here is what I got for my top-down game with no gravity after reading it, maybe itāll help some people passing by:
public static Vector3 PredictAim ( Vector3 shootPos, Vector3 targetPos, Vector3 targetVel, float projSpeed )
{
if (targetVel.sqrMagnitude <= 0f)
{
return targetPos;
}
else
{
Vector3 targetToBullet = shootPos - targetPos;
float distToTargetSqr = (shootPos - targetPos).sqrMagnitude;
float distToTarget = (shootPos - targetPos).magnitude;
Vector3 targetToBulletNorm = targetToBullet / distToTarget;
float tarSpeed = targetVel.magnitude;
float tarSpeedSqr = targetVel.sqrMagnitude;
Vector3 tarVelNorm = targetVel / tarSpeed;
float projSpeedSqr = projSpeed * projSpeed;
float cosTheta = Vector3.Dot(targetToBulletNorm, tarVelNorm);
float offsetSqrPart = 2 * distToTarget * tarSpeed * cosTheta;
offsetSqrPart *= offsetSqrPart;
float offset = Mathf.Sqrt(firstEqPart + 4 * (projSpeedSqr - tarSpeedSqr) * distToTargetSqr);
float estimatedTravelTime = (-2 * distToTarget * tarSpeed * cosTheta + offset) / (2 * (projSpeedSqr - tarSpeedSqr));
if (estimatedTravelTime < 0 || estimatedTravelTime == float.NaN)
{
return targetPos;
}
else
{
return targetPos + tarVelNorm * tarSpeed * estimatedTravelTime;
}
}
}
Hi!
I know that this is a 9 year old post, but in case somebody is struggling with the same problem I found a very good tutorial on youtube that solves this problem.
The solution here is based on the quadratic equation and law of cosines and it predicts the intersection point almost perfectly.
Here is the link, āPredictive Aim in Unityā: