c# - 如何在 Unity 中每次更新时插入一个获得新位置的相机?

标签 c# unity-game-engine interpolation

我有一个物理划船设备,它不断地将划船比赛的剩余距离发送给 Unity(即完成比赛还剩 350m)。当我尝试相应地更新玩家的位置(仅限 Z 轴)时,运动不稳定。 我怎样才能插入这种运动以使其更平滑?

我的第一次尝试是这样的:

void Update()
{
   player.position = new Vector3(player.position.x, player.position.y, 
   pm5.Pm5_distance);
}

这导致了运动的不稳定,可能是因为玩家只是被传送到下一个位置。

接下来我尝试移动到下一个位置,但我不确定我是否正确执行了操作,或者这是否有效,因为我的播放器每帧都会收到一个新位置:

private float startTime;
private float journeyLength;
public float speed = 5.0F;

void Start()
{
    startTime = Time.time;
}

void Update()
{
    if (player.position != new Vector3(player.position.x, 
    player.position.y, pm5.Pm5_distance))
    {
        journeyLength = Vector3.Distance(player.position, new 
        Vector3(player.position.x, player.position.y, pm5.Pm5_distance));

        float distCovered = (Time.time - startTime) * speed;

        float fracJourney = distCovered / journeyLength;

        transform.position = Vector3.Lerp(player.position, new 
        Vector3(player.position.x, player.position.y, pm5.Pm5_distance), 
        fracJourney);
    }

}

尽管这不会引发错误,但它似乎也无法解决我的问题。也许整个概念都是错误的?如果有人能在这里帮助我,我会很高兴。

编辑 2019 年 4 月 25 日: 通过尝试使用我的大卫代码,我到达这里:

    void Update()
    {

        if (useLerpMovementModel)
        {
            float newDistance = pm5.Pm5_distance;

            if (player.position.z != newDistance)
            {
                // Distance moved
                float distCovered = journeyLength - pm5.Pm5_distance;

                // Fraction of journey completed = current distance divided by total distance.
                float fracJourney = distCovered / journeyLength;

                // Set our position as a fraction of the distance between the markers.
                transform.position = Vector3.Lerp(player.position, new Vector3(player.position.x, player.position.y, newDistance), fracJourney);
            }
        }
        else
        {
            player.position = new Vector3(player.position.x, player.position.y, journeyLength - pm5.Pm5_distance);
        }

    }

我不确定这是否会起到任何作用,但与player.position = new Vector3(player.position.x,player.position.y,journeyLength - pm5.Pm5_distance)相比,这在平滑运动方面是否有任何作用);

最佳答案

下面这行实际上是一个不正确的计算:

journeyLength = Vector3.Distance(player.position, new 
        Vector3(player.position.x, player.position.y, pm5.Pm5_distance));

您需要存储旅程开始和结束时的位置,以便可以在它们之间插入玩家的位置。

我将尝试通过获取您的代码并添加注释来解释必要的内容。我还包括了我建议的更改以及其他更改:

private float journeyLength;
private Vector3 startPosition;
private Vector3 endPosition;

void Start()
{
    // The total length of the journey, let's imagine it's 100
    // This assumes that when this Start() method is called that
    // pm5.Pm5_distance is equal to the journey length
    journeyLength = pm5.Pm5_distance;
    // Store the player's starting position
    // This will be used to interpolate between start/end
    startPosition = player.position;
    // Store the position that the player will be at when the journey is complete
    // This will be used to interpolate between start/end
    endPosition = startPosition + Vector3.forward * journeyLength;
}

void Update()
{
    // I am assuming that 'pm5.Pm5_distance' is the remaining distance
    if (pm5.Pm5_distance > 0f) 
    {
        // Take the remaining distance from the total journey length to get
        // the current distance travelled. Let's imagine the remaining distance is 50:
        // This will end up being 100 - 50 = 50 units travelled into the journey
        float distCovered = journeyLength - pm5.Pm5_distance;

        // We now get the fraction of the journey that that distance equates to, 
        // which in this case will be 0.5
        float fracJourney = distCovered / journeyLength;

        // Interpolate the players position from where it originally started
        // to the position at the end of the journey (the one we calculated in Start())
        transform.position = Vector3.Lerp(startPosition, endPosition, fracJourney);
    }

}

最后一点,了解 Vector3.Lerp() 函数的工作原理非常重要: 它采用两个向量并在它们之间插值 0 到 1 之间的值。

如果值为 0,则返回第一个向量。

如果值为 1,则返回第二个向量。

如果值为 0.5,则返回位于两者之间的向量。

因此您可以看到,在上面的示例中,fracJourney 为 0.5,这意味着对于帧,玩家的位置将恰好位于比赛的一半位置。 但在下一帧中,fracJourney 将被重新计算,比如 0.55。 在该帧中,新位置将比前一帧中的位置稍微向前计算。

这样一直持续下去,直到最终距离比赛终点为 0。

关于c# - 如何在 Unity 中每次更新时插入一个获得新位置的相机?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55834367/

相关文章:

c# - 连接池错误 LINQ to SQL

c# - 调用 UserControl 不起作用

c# - 为什么使用 Time.timeScale 制作减速效果时会将分辨率更改为全屏?

c# - unity android 忽略游戏对象拖放之间的碰撞

python - 计算具有不同采样点数量的离散函数的平均值

python - 如何使用 scipy.interpolate.splrep 插值曲线?

c# - 等效于 Objective C BitConverter

c# - MethodInvoker 与 Control.BeginInvoke 的操作

unity-game-engine - 如何扩展Unity应用程序?

python - 使用 numpy interp 右