如何在给定的持续时间内为贝塞尔曲线设置动画

时间:2017-11-12 13:11:54

标签: c# unity3d

我通过将以下脚本添加到检查器中的空游戏对象来创建贝塞尔曲线。当我运行代码时,这将立即绘制完成曲线。如何在给定的时间段内为其设置动画,例如2或3秒?

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;
}

}

2 个答案:

答案 0 :(得分:4)

使用协程:

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;
    }

}

编辑:为通话添加了特定的持续时间。

注意:如果duration / numPoints可能小于Time.deltaTime,您可能需要使用此方法,每帧可以绘制多个点:

    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;
        }
    }

答案 1 :(得分:0)

这是Ed Marty Answers的增强版。 为了使协同程序在给定的持续时间内构建曲线,你可以这样做

waitDur = duration / numOfPoints;

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;
    }

}