I have created a bezier curve by adding the following script to an empty game object in the inspector. This draws to complete curve at once when I run the code. How can I animate it over a given period of time, say 2 or 3 seconds?
public class BCurve : MonoBehaviour {
LineRenderer lineRenderer;
public Vector3 point0, point1, point2;
int numPoints = 50;
Vector3[] positions = new Vector3[50];
// Use this for initialization
void Start () {
lineRenderer = gameObject.AddComponent<LineRenderer>();
lineRenderer.material = new Material (Shader.Find ("Sprites/Default"));
lineRenderer.startColor = lineRenderer.endColor = Color.white;
lineRenderer.startWidth = lineRenderer.endWidth = 0.1f;
lineRenderer.positionCount = numPoints;
DrawQuadraticCurve ();
}
void DrawQuadraticCurve () {
for (int i = 1; i < numPoints + 1; i++) {
float t = i / (float)numPoints;
positions [i - 1] = CalculateLinearBeziearPoint (t, point0, point1, point2);
}
lineRenderer.SetPositions(positions);
}
Vector3 CalculateLinearBeziearPoint (float t, Vector3 p0, Vector3 p1, Vector3 p2) {
float u = 1 - t;
float tt = t * t;
float uu = u * u;
Vector3 p = uu * p0 + 2 * u * t * p1 + tt * p2;
return p;
}
}
You can extend an open Bézier path. To do so, briefly click one of the path's two end points with the Bézier tool while holding down the SHIFT key. You can then add further Bézier points by clicking. Bézier paths can be connected to other Bézier paths and also to lines, rectangles, polygons and ellipses.
In animation applications, such as Adobe Flash and Synfig, Bézier curves are used to outline, for example, movement. Users outline the wanted path in Bézier curves, and the application creates the needed frames for the object to move along the path.
Use a coroutine:
public class BCurve : MonoBehaviour {
LineRenderer lineRenderer;
public Vector3 point0, point1, point2;
int numPoints = 50;
Vector3[] positions = new Vector3[50];
// Use this for initialization
void Start () {
lineRenderer = gameObject.AddComponent<LineRenderer>();
lineRenderer.material = new Material (Shader.Find ("Sprites/Default"));
lineRenderer.startColor = lineRenderer.endColor = Color.white;
lineRenderer.startWidth = lineRenderer.endWidth = 0.1f;
StartCoroutine(DrawQuadraticCurve (3));
}
IEnumerator DrawQuadraticCurve (float duration) {
//Calculate wait duration for each loop so it match 3 seconds
float waitDur = duration / numPoints;
for (int i = 1; i < numPoints + 1; i++) {
float t = i / (float)numPoints;
lineRenderer.positionCount = i;
lineRenderer.setPosition(i - 1, CalculateLinearBeziearPoint (t, point0, point1, point2));
yield return new WaitForSeconds(waitDur);
}
}
Vector3 CalculateLinearBeziearPoint (float t, Vector3 p0, Vector3 p1, Vector3 p2) {
float u = 1 - t;
float tt = t * t;
float uu = u * u;
Vector3 p = uu * p0 + 2 * u * t * p1 + tt * p2;
return p;
}
}
EDIT: Added a specific duration to the call.
Note: If duration / numPoints
is likely to be less than Time.deltaTime
, you may want to use this method instead, which can draw multiple points per frame:
IEnumerator DrawQuadraticCurve (float duration) {
float progressPerSecond = 1 / duration;
float startTime = Time.time;
float progress = 0;
while (progress < 1) {
progress = Mathf.clamp01((Time.time - startTime) * progressPerSecond);
int prevPointCount = lineRenderer.positionCount;
int curPointCount = progress * numPoints;
lineRenderer.positionCount = curPointCount;
for (int i = prevPointCount; i < curPointCount; ++i) {
float t = i / (float)numPoints;
lineRenderer.setPosition(i, CalculateLinearBeziearPoint (t, point0, point1, point2));
}
yield return null;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With