【问题标题】:How to animate a bezier curve over a given duration如何在给定的持续时间内为贝塞尔曲线制作动画
【发布时间】:2017-11-12 13:11:54
【问题描述】:

我通过将以下脚本添加到检查器中的空游戏对象来创建贝塞尔曲线。当我运行代码时,这会立即绘制完成曲线。如何在给定的时间段内(例如 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;
}

}

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    使用协程:

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

    【讨论】:

    • 根据我对问题的理解,chronos 想要在特定持续时间内为贝塞尔曲线制作动画。
    • @Hilarious404 然后 WaitForSeconds 参数应该是 duration/numPoints
    • 除非最终小于Time.deltaTime,在这种情况下,需要在单个帧中多次运行循环。
    • @EdMarty 曲线没有从零开始渲染,我该如何解决?
    【解决方案2】:

    这是对 Ed Marty Answers 的增强。 要使协程在给定的时间内构建曲线,您可以这样做

    waitDur = 持续时间 / 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;
        }
    
    }
    

    【讨论】:

    • 我已将您的更改纳入我的回答中
    • 对不起,我想添加评论,但我不能
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多