这篇博客,聊一聊在游戏开发中,控制角色或者其他物体的平滑移动。现实中,一个物体,从静止加速到匀速运动状态,或者从匀速运动状态变为静止状态,都会有一个过程。就像人走路,或者汽车开动。
一个物体在运动状态下,会有一个速度变量,也就是我们期望的速度。而从静止到运动状态的过程,会有一个加速度。
而游戏开发中,要做到一个物体平滑的运动,也就是模拟出这个从静止,通过加速度,达到期望速度的过程。
游戏是按帧运行的,在初始的时候,目标运动速度为0,随着每一帧的流逝,目标速度会不断累加一帧中的加速度,当累加到期望速度时,则会以期望速度来运动。
代码如下,这里是在 Unity 中实现的,但是原理对于所有游戏引擎通用
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MovingSphere : MonoBehaviour
{
// 用户设定最大期望速度
[SerializeField, Range(0f, 100f)] private float maxSpeed = 10f;
// 用户设定最大加速度
[SerializeField, Range(0f, 100f)] private float maxAcceleration = 10f;
// 当前的运动速度
private Vector3 velocity;
// Update is called once per frame
void Update()
{
// 通过读取用户输入,来确定期望速度向量(向量包含了大小和方向)
Vector2 playerInput;
playerInput.x = Input.GetAxis("Horizontal");
playerInput.y = Input.GetAxis("Vertical");
Vector3 desiredVelocity = new Vector3(playerInput.x, playerInput.y, 0.0f) * maxSpeed;
// 计算这一帧中的最大加速度(现实中是以秒为单位,而游戏运行是以帧为单位)
float maxSpeedChanged = maxAcceleration * Time.deltaTime;
// 下面的代码是将当前速度限制为最大期望速度
if (velocity.x < desiredVelocity.x)
{
velocity.x = Mathf.Min(velocity.x + maxSpeedChanged, desiredVelocity.x);
}
else if (velocity.x > desiredVelocity.x)
{
velocity.x = Mathf.Max(velocity.x - maxSpeedChanged, desiredVelocity.x);
}
if (velocity.y < desiredVelocity.y)
{
velocity.y = Mathf.Min(velocity.y + maxSpeedChanged, desiredVelocity.y);
}
else if (velocity.y > desiredVelocity.y)
{
velocity.y = Mathf.Max(velocity.y - maxSpeedChanged, desiredVelocity.y);
}
// 得到了当前速度,就可以计算当前这一帧的位移
Vector3 displacement = velocity * Time.deltaTime;
// 将物体的当前位置,累加上这一帧的位移,就是最终的移动
transform.localPosition += displacement;
}
}