How can I make a missile home to an enemy in arc fashion? (Unity 4.3 2D)

I am building a 2D game and i’ve managed to make homing missiles with the following code:

`
Vector2 destination = player.transform.position - transform.position;
lastPos = destination;
float angle = Mathf.Atan2(destination.y, destination.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
			
destination.Normalize ();
transform.position += new Vector3 (destination.x, destination.y, 0) * speed * Time.deltaTime;
`

I’ve made it so that the rocket simply travels in a straight line towards the player. Can anyone guide me in the right direction to make the rocket travel in an arc towards the player instead of a straight line.

Use a bezier curve of two point

	private Vector3 CalculateBezierPoint (float t, Vector3 startPosition, Vector3 endPosition, Vector3 controlPoint) {
		float u = 1 - t;
		float uu = u * u;

		Vector3 point = uu * startPosition;
		point += 2 * u * t * controlPoint;
		point += t * t * endPosition;

		return point;
	}

Call it from update something like

this.transform.position = CalculateBezierPoint(currentDuration/duration,startPos,endPos,cp);

currentDuration += Time.deltaTime;

where “duration” is total time.

More info on wikipedia for bezier curves: File:Bézier 2 big.gif - Wikipedia

I suggest, using iTween, where you set your waypoints, the easiest way to define this waypoints instead of using a formula, just add 4, the first, your origin, second and third, at 1 third between origin and destiny but with the y above them depending on how your desired arc is, and the fourth your destiny, itween WILL interpolate the movements, after defining that you could play a little with the type of movement, as linear, cuadratic, spring, etc, the code for i tween is something like this

public Transform[] waypoints;
public float m_speed = 1.0f;
public GameObject player1;
private int i = 0;
private bool moving = false;
 
public void Update() {
if (!moving && i < waypoints.Length - 1) {
i++;
moving = true;
iTween.MoveTo(player1,iTween.Hash("position",waypoints*,"speed",m_speed,"easetype","linear", "oncompletetarget",gameObject, "oncomplete", "Done"));*

}

}

public void Done() {
moving = false;
}

And another solution to add to the mix. Use the Sin() function to calculate a loft for the missile over the distance traveled. Take the script below and attach to a sphere in the scene. Click the mouse to shoot the sphere to that position:

#pragma strict
 
var traveling = false;

function Update() {
	if (!traveling && Input.GetMouseButtonDown(0)) {
		var pos = Input.mousePosition;
		pos.z = 10.0;
		pos = Camera.main.ScreenToWorldPoint(pos);
		ArcToTarget(pos, 0.35, 1.0);
	}
 } 
 
function ArcToTarget(targetPos : Vector3, arcFraction : float, time : float) {
	traveling = true;
	var startPos = transform.position;
	var timer = 0.0;
	var arcDist = (targetPos - startPos).magnitude * arcFraction;
	
	while (timer < time) {
		var pos = Vector3.Lerp(startPos, targetPos, timer / time);
		pos.y += Mathf.Sin(Mathf.PI * timer / time) * arcDist;
		transform.position =  pos;
		timer += Time.deltaTime;
		yield;
	}
	transform.position = targetPos;
	traveling = false;
}

Let’s assume we have 3 points: A (start), B (middle) and C (end). We linearly interpolate over time between A and B, as well as B and C. Meanwhile, we interpolate between the result of the two. The code presented below should work perfectly. Simply call QuadraticCurve in the Update() method. Subsequently, increment the time as we want to go from 0 to 1: time += Time.deltaTime;

private Vector3 LinearInterpolate(Vector3 start, Vector3 end, float time)
{
    return start + (end - start) * time;
}

private Vector3 QuadraticCurve(Vector3 start, Vector3 middle, Vector3 end, float time)
{
    Vector3 line1 = LinearInterpolate(start, middle, time);
    Vector3 line2 = LinearInterpolate(middle, end, time);
    return LinearInterpolate(line1, line2, time);
}
private void Update()
{
    transform.position = QuadraticCurve(startPoint, middlePoint, endPoint, 
    duration);
    durtation += Time.deltaTime;
}

You can use a sine curve for that. Attach the script below to your projectile, and use Projectile.Spawn() to spawn a projectile that will home in on its target. You can set arcFactor to adjust the height and speed to adjust how fast it travels. For an explanation of the math involved, you can look at this article where the script was taken from: https://blog.terresquall.com/2019/11/coding-projectiles-for-your-tower-defense-game-part-2/

public class Projectile : MonoBehaviour {
    public float speed = 8.5f; // Speed of projectile.
    public float radius = 1f; // Collision radius.
    float radiusSq; // Radius squared; optimisation.
    Transform target; // Who we are homing at.

    Vector3 currentPosition; // Store the current position we are at.
    float distanceTravelled; // Record the distance travelled.

    public float arcFactor = 0.5f; // Higher number means bigger arc.
    Vector3 origin; // To store where the projectile first spawned.

    void OnEnable() {
        // Pre-compute the value. 
        radiusSq = radius * radius;
        origin = currentPosition = transform.position;
    }
    
    void Update() {
        // If there is no target, destroy itself and end execution.
        if ( !target ) {
            Destroy(gameObject);
            // Write your own code to spawn an explosion / splat effect.
            return; // Stops executing this function.
        }

        // Move ourselves towards the target at every frame.
        Vector3 direction = target.position - currentPosition;
        currentPosition += direction.normalized * speed * Time.deltaTime;
        distanceTravelled += speed * Time.deltaTime; // Record the distance we are travelling.

        // Set our position to <currentPosition>, and add a height offset to it.
        float totalDistance = Vector3.Distance(origin, target.position);
        float heightOffset = arcFactor * totalDistance * Mathf.Sin( distanceTravelled * Mathf.PI / totalDistance );
        transform.position = currentPosition + new Vector3( 0, 0, heightOffset );

        // Destroy the projectile if it is close to the target.
        if ( direction.sqrMagnitude < radiusSq ) {
            Destroy(gameObject);
            // Write your own code to spawn an explosion / splat effect.
            // Write your own code to deal damage to the .
        }  
    }

    // So that other scripts can use Projectile.Spawn to spawn a projectile.
    public static Projectile Spawn(GameObject prefab, Vector3 position, Quaternion rotation, Transform target) {
        // Spawn a GameObject based on a prefab, and returns its Projectile component.
        GameObject go = Instantiate(prefab, position, rotation);
        Projectile p = go.GetComponent<Projectile>();

        // Rightfully, we should throw an error here instead of fixing the error for the user. 
        if(!p) p = go.AddComponent<Projectile>();

        // Set the projectile's target, so that it can work.
        p.target = target;
        return p; 
    }
}