您认为使用Vector3.Lerp 在开始值和结束值之间逐渐插值是正确的。但是,实现和用例并不完全适合您尝试做的事情。
由于您只更改运动的单个轴,因此我不会使用Vector3.Lerp,而是使用Mathf.Lerp,因为您只是更改位置的 x 轴。
您使用的是while 循环而不是Update,这意味着程序将停留在该循环内,直到该过程完成。它立即移动到下一点的原因是由于您的if 条件。您正在从当前位置中减去 2.5 的值,然后不断检查当前位置 x 是否大于新位置,这始终是正确的。它会立即将您的当前位置设置为新位置,然后跳出您的 while 循环。另一个问题是您正在使用GetKeyDown,它只发生在用户单击键的一帧。 Lerps 应该随着时间的推移完成,而不是立即完成。
我不会将您的逻辑放在Update 中,而是考虑将实际运动转移到一个称为Coroutine 的特殊函数中。将Courtines 视为一个在多个帧上完成的过程,并跳回到它在前一帧中停止的位置。 Coroutines 非常强大,但请在过度使用它们之前仔细阅读文档以深入了解它们的作用。
现在开始实施。我不完全确定你的车道设置,但假设你有 3 条车道,类似于其他无限跑道游戏。我会将输入检测保留在Update 中,并允许玩家从中间左右跳跃,但不会偏离轨道,也不会在跳跃时跳跃。我也会用时间而不是速度来控制Lerp的跳跃,你可以很容易地把它改成速度。
[SerializeField] private float TimeForJump = 0.25f;
[SerializeField] private float JumpOffset = 2.5f;
// I am assuming your setup for lanes is -1 | 0 | 1
private int lane = 0;
private Coroutine PlayerJumping = null;
void Update()
{
// no need to detect input if we are already jumping
if(PlayerJumping == null)
{
// instead of 'a' and 'd' you can use GetAxis to allow for arrow key and wasd support
// it is also an easy way to determine direction when adding or subtracting for a goal location
float horzInput = Input.GetAxis("Horizontal");
if (horzInput < 0 && lane > -1)
{
PlayerJumping = StartCoroutine(Jump(-1));
lane--;
}
else if(horzInput > 0 && lane < 1)
{
PlayerJumping = StartCoroutine(Jump(1));
lane++;
}
}
// simulating your movement
transform.position = new Vector3(transform.position.x, transform.position.y + 0.1f, transform.position.z);
}
/// <summary>
/// Horizontally have the player jump
/// </summary>
private IEnumerator Jump(float direction)
{
// store our current position
float currentXPos = transform.position.x;
// our goal position
float goalXPos = currentXPos + (direction * JumpOffset);
// timer for how long it has passed since we started the jump
float jumpTimer = 0.0f;
// continue the lerp for the time we have left
while(jumpTimer <= TimeForJump)
{
transform.position = new Vector3(Mathf.Lerp(currentXPos, goalXPos, jumpTimer / TimeForJump), transform.position.y, transform.position.z);
// increment the time that has passed
jumpTimer += Time.deltaTime;
yield return null;
}
// set our position directly in case of floating point errors
transform.position = new Vector3(goalXPos, transform.position.y, transform.position.z);
// set the coroutine to null so we can jump again
PlayerJumping = null;
}
由于我不确定您的实施是如何完成的,因此我对车道和其他一般设置有一些假设。答案非常通用,因此可以根据您的需要进行调整。如果您愿意,您也可以将输入交换回GetKeyDown,我使用它的唯一原因是您可以获得箭头键以及wasd 输入。