在本教程中,我们将了解 Unity 中的 Time.deltaTime 是什么,以及如何使用它。
本教程的视频版本目前尚未提供该语言版本。
视频文字稿
大家好。在本教程中,我们将了解 Unity 中的 Time.deltaTime 是什么,以及如何使用它。
本教程适合刚开始在 Unity 中使用 C# 编写脚本的初学者,因为这是一个非常基础且重要的概念。你会在许多脚本和教程中反复遇到它,因此值得深入理解。
本教程基于 Unity 2022 制作,不过 Time.deltaTime 在多个版本中都已存在,并且很可能在未来版本中继续保留。
Time.deltaTime 是一个变量,用来表示上一帧与当前帧之间经过的时间,单位为秒。换句话说,它表示完成上一帧所花费的时间。

它的作用是让移动和动画不受帧率影响。通常的做法是在每一帧中,将物体的每秒速度乘以 Time.deltaTime。
这样一来,每一帧的位移会根据当前帧率自动调整,从而保证在不同性能的设备上都能保持相同的移动速度。
下面我们通过一个非常简单的示例来说明这一点:让一个物体沿某个轴以恒定速度移动。将一个对象添加到场景中,并使用 Isometric 视角从上方观察场景。

为该对象添加一个 C# 脚本,例如命名为 movement,然后创建一个 Vector3 变量,用来表示每秒移动一个单位的位移:
private Vector3 obVelocity = new Vector3(0.0f, 0.0f, 1.0f);
我们知道 Update 会在每一帧被调用,但我们无法预知游戏每秒会运行多少帧,因为这取决于多种因素。
如果帧率始终保持在每秒 50 帧,我们可以将 obVelocity 修改为 (0.0f, 0.0f, 0.02f),这样在每次调用 Update 时移动 0.02 个单位,也就是每一帧移动 0.02 个单位,从而实现每秒移动一个单位。
由于现实中无法保证固定帧率,因此我们在 Update 中这样编写:
transform.position += (obVelocity * Time.deltaTime);

保存脚本,返回 Unity 编辑器观察结果。你会看到物体做匀速直线运动,每秒在场景中移动一个单位。
总结一下:如果想让物体以某个特定速度移动,首先将该速度定义为一个变量,然后在 Update 函数中将其乘以 Time.deltaTime,就像刚才演示的那样。
接下来我们再看一个示例。
在当前使用的场景中,Main Camera 添加了一个移动脚本,用于检测方向键输入,使用的是 Input.GetAxis 的 Horizontal 和 Vertical。
Horizontal 和 Vertical 的取值范围都是从 -1 到 1。如果在 Update 函数中直接将这些值乘以 Time.deltaTime,就可以实现每秒在场景中移动一个单位。但这种方式无法调节移动速度。
为了解决这个问题,最简单的方法是定义一个带有 Serialized 修饰符的 private 变量。这样在 Editor 中运行游戏时,可以在 Inspector 中看到并修改它。
在视频示例中,这个变量名为 speed,初始值为 12。

在 Update 函数中,由于角色绑定了 Character Controller 组件,因此移动是通过 controller.Move 来实现的。Character Controller 使用 Move 函数进行移动。
该函数的参数较长,可以分为两部分。
第一部分根据用户输入计算 X 轴和 Z 轴方向的位移,输入值存储在名为 move 的变量中,该变量是一个 Vector3。
第二部分是在角色跳跃时计算重力产生的垂直位移。

Time.deltaTime 同时用于轴向移动的计算以及重力带来的垂直移动计算。不过我们在这里忽略第二部分,因为那需要更深入的讨论,我们重点关注第一部分。
与第一个示例中的立方体类似,移动向量 move 会乘以 Time.deltaTime,同时还会乘以 float 类型变量 speed。
接着我切换到 Unity 编辑器并运行游戏,演示如何在游戏运行过程中,通过修改脚本面板中的 Speed 参数值,实时改变角色的移动速度。
通过这种方式,可以在游戏开始前调试并校准合适的移动速度。
由于该速度会与 Time.deltaTime 相乘,因此无论在哪种设备上运行,只要帧率不同,最终效果仍然保持一致。
因为 speed 是代码中的一个变量,所以也可以在游戏过程中根据某些事件动态修改它。
例如,玩家可能喝下一瓶药水,使移动速度提高两倍,或者相反地减慢移动速度。
关键在于,这个速度不会受到帧率影响,因此在不同设备上都会保持一致,这正是 Time.deltaTime 的作用。
总结来说,在本视频中我们通过两个简单示例学习了如何使用 Time.deltaTime。
接下来我会发布一个关于使用 Slerp 实现旋转的视频,其中也会使用 Time.deltaTime 来实现与帧率无关的恒速旋转。
本教程到此结束。我们下次再见。