2D AI: How to get the AI to aim ahead of its target?

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?

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 :slight_smile:

Scribe

A relatively simple way of performing a prediction that I’ve found was by using:

Vector3 PredictPosition(GameObject target){
		Vector3 velocity = target.GetComponent<Rigidbody2D>().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;
        }
    }
}