The
FixedUpdate()功能每隔一段固定时间运行一次,这个时间由
Time.fixedDeltaTime定义(可以通过
TimeManager (Fixed Timestep)设置或在运行时直接设置
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
在这个示例中,您可以看到角色每帧向前跳跃的不同量,而且您无法保证游戏运行的帧率,因此可能会更糟。但是有几种方法可以使您的角色移动平稳。
Put your code in an Update() loop instead of a FixedUpdate() loop, this will move the position of the character each rendered frame. Along with this you can multiply the movement speed by Time.deltaTime which is the time since the previous frame was rendered (aka time since Update() was last ran and the character was moved)
Use Vector3.Lerp(..)/Quaterion.Lerp(..) or Vector3.MoveTowards(..)/Quaternion.RotateToward(..) using a time/step value multiplied by Time.deltaTime to interpolate the character movement keeping it moving smoothly in relation to the game framerate.
If your character has a rigidbody component then you can simply just set the rigidbody interpolation to interpolate then move your character by calling:
characterRigidbody.MovePosition(wantedPosition);
characterRigidbody.MoveRotation(wantedRotation);
As a replacement to your existing transform movements (keeping your code inside of the FixedUpdate() loop)
But note that continuing to have your Input.* calls inside a FixedUpdate() is polling them more than needed so you might want to move them over into an Update() splitting the movement code and input listening code if you decide to do this. (I develop android games so maybe on PC this isn't worth worrying about as much, but probably still worth changing)
对于这个问题,直接的代码块回答可能是尝试这个,它是解释1和2的结合:
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);
}
transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime / lerpSmoothingTime);
transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, Time.deltaTime / lerpSmoothingTime);
}
如果你想更详细地了解如何平滑移动物体,学习有关lerps的知识或者只是需要更多的示例,请查看这份指南,了解如何在Unity中修复运动卡顿问题。请访问
how to fix movement stutter in Unity。
Vector3.MoveTowards
或者Vector3.Lerp
吗?这两个函数都有平滑移动的示例... - Ron Beyer