如何扩展在 C# 和 Unity 中使用二次插值创建的曲线?

How to extend the curve created using quadratic interpolation in C# & Unity?

我正在尝试使用二次插值法向玩家的位置扔石头。岩石只是沿着曲线移动。然而,如果玩家移动,石头就会开始循环并回到原来的位置。一旦它到达曲线的末端,我就停止了跟随曲线的岩石,并向岩石的刚体施加力,但它只在特定的例子中起作用。我想知道是否有一种方法可以延长曲线,使岩石撞击地面并使用我已有的代码自行破坏。我正在使用的代码如下。提前致谢。代码如下。

二次插值码(每帧运行)

private void FollowQuadraticPath()
    {
        interpolateAmount = (interpolateAmount + Time.deltaTime) % 1f;
        pointAB.transform.position = Vector3.Lerp(transformerPosition, throwHeightPosition, interpolateAmount);
        pointBC.transform.position = Vector3.Lerp(throwHeightPosition, playerPosition, interpolateAmount);

        transform.position = Vector3.Lerp(pointAB.transform.position, pointBC.transform.position, interpolateAmount);
    }

伤害

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.GetComponent<PlayerHealth>())
        {
            Destroy(pointABInstance);
            Destroy(pointBCInstance);
            collision.gameObject.GetComponent<PlayerHealth>().DealDamage(damage);
            Destroy(gameObject);
        }
        else
        {
            Destroy(pointABInstance);
            Destroy(pointBCInstance);
            Destroy(gameObject);
        }
    }

这就是我想要发生的事情。假装玩家已经移动,岩石将继续并击中经过玩家点的地面。

相反,再次假装玩家不在那里,物体在到达地面之前被摧毁

编辑:检查我使用的解决方案的答案评论

我猜你在 Update 中使用 FollowQuadraticPath() 所以发生的事情是你总是将它与播放器的 当前更新 位置一起使用。

相反,我会使用 Coroutine。 Coroutine 有点像一个临时的 Update 方法,所以它有一个明确的开始和结束,你可以让局部变量在例程 运行ning 的所有帧中持续存在,并做一些类似

的事情
private IEnumerator FollowQuadraticPath()
{
    // Cash the target positions ONCE so they are not updated later
    var startAB = TransformerPosition;
    var targetAB = throwHeightPosition;
    var targetBC = playerPosition;

    // Iterates until 1 second has passed
    // linearly increasing interpolateAmount from 0 to 1    
    for(var interpolateAmount = 0f; interpolateAmount < 1f; interpolateAmount += Time.deltaTime)
    {
        pointAB.transform.position = Vector3.Lerp(startAB, targetAB, interpolateAmount);
        pointBC.transform.position = Vector3.Lerp(targetAB, targetBC, interpolateAmount);

        transform.position = Vector3.Lerp(pointAB.transform.position, pointBC.transform.position, interpolateAmount);

        // Tells Unity to "pause" the routine here, render this frame
        // and continue from here in the next frame
        yield return null;
    }

    // Destroy if it reaches the original player position
    Destroy (gameObject);
}

你 运行 这个 ONCE 例如在

private void Start ()
{
    StartCorouine(FollowQuadraticPath());
}

Start也可以是例程本身,如

private IEnumerator Start()
{
    var startAB = TransformerPosition;
    var targetAB = throwHeightPosition;

    .....
}

您不必担心终止例程,因为它要么到达原始玩家位置然后被摧毁,要么它之前撞到地面并被摧毁。在任何一种情况下,协程也会自动消失。


不过我不太明白的是,为什么您要为此进行 2 个额外的转换。为什么不简单地只用 Vector3 本身来计算

var ab = Vector3.Lerp(startAB, targetAB, interpolateAmount);
var bc = Vector3.Lerp(targetAB, targetBC, interpolateAmount);

transform.position = Vector3.Lerp(ab, bc, interpolateAmount);