当前,这是我的脚本,用于将播放器移动到场景中。如何使它平稳移动?
void FixedUpdate()
{
bool running = Input.GetKey(KeyCode.LeftShift);
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical");
bool isWalking = Mathf.Abs(h) + Mathf.Abs(v) > 0;
movement = ((running) ? runSpeed : walkSpeed) * new Vector3(h, 0.0f, v).normalized;
if (isWalking)
{
transform.position += movement * Time.fixedDeltaTime;
transform.LookAt(transform.position + movement);
}
}
答案 0 :(得分:10)
创建速度矢量:
Vector3 velocity = Vector3.zero;
将运动矢量添加到速度:
velocity += movement;
将速度添加到实际位置:
transform.position += velocity;
通过逐渐降低速度来平滑速度:
velocity *= 0.975f;
答案 1 :(得分:2)
FixedUpdate()函数在 Time.fixedDeltaTime 定义的每个固定间隔运行(您可以通过TimeManager (固定时间步长),或在运行时直接将 Time.fixedDeltaTime 设置为新值。
因为您以固定的间隔移动角色的位置和旋转,所以根据帧速率,角色将以较低的帧速率移动很多,或者仅以较高的帧速率移动每几帧。
例如,在0.02秒的固定时间范围内,游戏以每秒30帧的帧速率运行。(又名每0.033秒渲染一次),您的游戏将执行以下操作:
- [Time: 0.020s] Character position += 0.02
- [Time: 0.033s] Render frame with character at position 0.02
- [Time: 0.040s] Character position += 0.02
- [Time: 0.060s] Character position += 0.02
- [Time: 0.066s] Render frame with character at position 0.06
- [Time: 0.080s] Character position += 0.02
- [Time: 0.099s] Render frame with character at position 0.08
- [Time: 0.100s] Character position += 0.02
- [Time: 0.120s] Character position += 0.02
- [Time: 0.133s] Render frame with character at position 0.12
因此,在此示例中,您可以看到角色如何以每帧不同的量向前跳跃,并且不能保证游戏将以哪种帧速率运行,因此最终可能会变得更糟。
尽管有几种方法可以使角色平稳移动。
将代码放入 Update()循环而不是 FixedUpdate()循环中,这将移动每个渲染帧中字符的位置。与此相伴,您可以将移动速度乘以Time.deltaTime,这是自上一帧渲染以来的时间(即自上次运行Update()并移动角色以来的时间)
使用Vector3.Lerp(..) / Quaterion.Lerp(..)或Vector3.MoveTowards(..) / Quaternion.RotateToward(..),将时间/步长值乘以 Time.deltaTime 进行插值角色移动使其相对于游戏帧速率平稳地移动。
如果角色具有刚体分量,则只需将刚体插值设置为插值,然后通过调用来移动角色:
characterRigidbody.MovePosition(wantedPosition);
characterRigidbody.MoveRotation(wantedRotation);
作为现有转换动作的替代方法(将代码保留在FixedUpdate()循环中)
但是请注意,在FixedUpdate()中继续进行Input。*调用会使它们轮询的次数超过了需要,因此如果您决定执行以下操作,则可能需要将它们移到Update()中,以分割运动代码并输入监听代码做这个。 (我开发了android游戏,所以也许在PC上不必为此担心,但可能仍然值得更改)
尽管直接代码块可以回答问题,但可以尝试一下,这是解释1和2的组合。
// How long in seconds will it take the lerps to finish moving into position
public float lerpSmoothingTime = 0.1f;
private Vector3 targetPosition;
private Quaternion targetRotation;
void Update()
{
bool running = Input.GetKey(KeyCode.LeftShift);
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical");
bool isWalking = Mathf.Abs(h) + Mathf.Abs(v) > 0;
movement = ((running) ? runSpeed : walkSpeed) * new Vector3(h, 0.0f, v).normalized;
if (isWalking)
{
targetPosition += movement * Time.deltaTime;
targetRotation = Quaternion.LookRotation(targetPosition - transform.position);
}
// Always lerping as if we suddenly stopped the lerp as isWalking became false the stop would be sudden rather than smoothly moving into position/rotation
transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime / lerpSmoothingTime);
transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, Time.deltaTime / lerpSmoothingTime);
}
如果您想详细阅读有关平滑移动的物体,学习有关ler的知识,或者只想了解更多示例,请查阅how to fix movement stutter in Unity上的本指南。
答案 2 :(得分:0)
首先,如果您希望代码执行每个框架,则需要将其放入Update()方法。根据项目设置,FixedUpdate的调用间隔固定(您可以在“编辑”->“项目设置”->“时间”->“固定时间步长”中进行更改)。通常,FixedUpdate()用于与物理相关的东西。
答案 3 :(得分:0)
您可以使用Vector3.Lerp(...)
。
尝试以下代码:
float smoothTime = 0.125f;
Vector3 newPos;
...
void FixedUpdate()
{
bool running = Input.GetKey(KeyCode.LeftShift);
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical");
movement = ((running) ? runSpeed : walkSpeed) * new Vector3(h, 0.0f, v).normalized;
//Set the new position
if(movement.magnitude > 0)
newPos = transform.position + movement;
// Use Vector3.Lerp(...)
transform.position = Vector3.Lerp(transform.position, newPos, smoothTime);
transform.LookAt(transform.position);
}
希望对您有帮助。
答案 4 :(得分:0)
在FixedUpdate中移动它应该非常平滑。当然,Vector3.Lerp可以帮助您运动,但是为什么它首先不平滑?
我只能猜测您的相机具有正常的更新脚本,或者有一些刚体插值。您需要了解的有关平滑运动的所有信息都在这里进行了解释:
http://www.kinematicsoup.com/news/2016/8/9/rrypp5tkubynjwxhxjzd42s3o034o8