这篇博客,聊一聊在游戏开发中,控制角色或者其他物体的平滑移动。现实中,一个物体,从静止加速到匀速运动状态,或者从匀速运动状态变为静止状态,都会有一个过程。就像人走路,或者汽车开动。

一个物体在运动状态下,会有一个速度变量,也就是我们期望的速度。而从静止到运动状态的过程,会有一个加速度。

而游戏开发中,要做到一个物体平滑的运动,也就是模拟出这个从静止,通过加速度,达到期望速度的过程。

游戏是按帧运行的,在初始的时候,目标运动速度为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;
    }
}