Bezier curves for flight paths in Unity C#

For my mobile game I needed enemy space ships that would fly to random points in space within a specific area. When they reached the designated point, they would choose a new point and the process would repeat. First I tried the easiest solution: transform.LookAt(), which worked, but the space ships had a specific turn radius and under some circumstances would circle the destination point indefinitely. I could increase the distance that was required for the ship to “reach” the checkpoint but I wanted to guarantee consistency.

Bezier curves would allow me to have consistent flight patterns without having to fine tune parameters in order to avoid unintended behaviors.

using UnityEngine;
using System.Collections;

public class Test : MonoBehaviour
{
[SerializeField]
private float dist; //the distance of the current curve on a scale of 0 to 1
[SerializeField]
private Vector3[] points; // an array of Vector3 points to calculate the curve. You can adjust the formula to use your desired amount of points.
[SerializeField]
private float min; //the minimum distance at which to place a points[]
[SerializeField]
private float max; //the maximum distance at which to place a points[]
[SerializeField]
private float speed; //the speed modifier for moving the ship along the curve


void Awake()
{
CalcInitPoints();
}

Vector3 CalculateBezierPoint(float t,
Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3) // returns the vector3 of the desired point along the curve. this vector3 will be the transform.position of the ship
{
float u = 1f - t;
float tt = t * t;
float uu = u * u;
float uuu = uu * u;
float ttt = tt * t;

Vector3 p = uu * p0;
p += 2 * u * t * p1;
p += tt * p2;

return p;
}

void Update ()
{
MoveBezier(); //for the purpose of demonstration, the flight is continuously calculated on Update().
}

private void CalcInitPoints() //create the initial points for the curve
{
for (int i = 0; i <= 4; i++)
{
points[i] = new Vector3(Random.Range(min, max), Random.Range(min, max), Random.Range(min, max));
}
}

private void NewPoints() //NewPoints is used only after there are points already existing
{

points[0] = points[2]; //re-use the third point
points[1] = (points[2] + (-0.5f * (points[1] - points[2]))); //the second point becomes the new tangent calculated using the third and second point
points[2] = new Vector3(Random.Range(min, max), Random.Range(min, max), Random.Range(min, max));//the third point is the new random Vector3
}

private void MoveBezier() //updates every frame to move the ship along the curve using Time.deltaTime
{
Vector3 nextPoint = CalculateBezierPoint(dist, points[0], points[1], points[2], points[3]); //injects dist (0-1 which increases by deltaTime) into the bezier formula
transform.position = nextPoint; //translate the position of the ship
if (dist <= 1f) //check every frame to see if the end of the curve has been reached
{
dist += Time.deltaTime * speed;
transform.LookAt(CalculateBezierPoint(dist, points[0], points[1], points[2], points[3])); //keeps the ship facing in the direction that it is flying
}
else
{
NewPoints(); //when the end of the curve has been reached, create a new curve and then reset the dist to zero
dist = 0;
}
}
}

The length and point on the curve is measured between 0 and 1.  The position of the ship is set equal to a specific point on the curve which is being increased by Time.deltaTime. Once the distance has reached 1, a new point is made, a new curve is calculated, and the distance along the curve is set back to 0. Now we have random flight paths using bezier curves.

 

Special thanks and credits to Herman Tulleken for being my source: http://devmag.org.za/2011/04/05/bzier-curves-a-tutorial/ His function CalculateBezierPoint does a great job of breaking down the cubic bezier formula:

[x,y]=(1t)3P0+3(1t)2tP1+3(1t)t2P2+t3P3
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s