这是关于在 Unity 2022 中创建 “Look At” 脚本的两个教程中的第二个,用来让一个对象指向另一个对象。


本教程的视频版本目前尚未提供该语言版本。


视频文字稿

大家好!

这是关于在 Unity 2022 中创建 “Look At” 脚本的两个教程中的第二个,用来让一个对象指向另一个对象。

在第一部分中,我们分析了问题,并实现了一个会让对象瞬间旋转的解决方案;而在本教程中,我们将使用 Quaternions 和 Slerp 来实现更慢、更平滑的旋转效果。

在本教程中,我假设你已经熟悉 Time.deltaTime 和 Quaternion.Slerp 方法等概念,因为我在其他教程中已经讲解过这些内容。如果你还不熟悉这些主题,建议先查看相关教程。

在上一期教程中,我们讨论了摄像机的全局坐标轴和局部坐标轴,用来识别表示其朝向的轴,以及指示围绕哪个轴进行旋转。

然后我们将问题简化到二维平面,并计算出 3D 模型 Surveillance Camera 应该围绕的旋转角度。

在我们的脚本中,这个角度称为 deltaAngle,单位为度。

要使用 Slerp,我们需要三个元素:

表示初始朝向的 quaternion;

表示目标朝向的 quaternion;

以及一种方法,用来在游戏执行的每一帧中指示我们在从初始朝向过渡到最终朝向的过程中所处的位置,范围为 0 到 1。

第一点最简单:transform 的 rotation 属性本身就是以 quaternion 形式表示对象的朝向,因此我们将使用 transform.rotation。

第二点也不复杂:给定一个以 quaternion 表示的初始朝向,表示通过旋转该初始朝向而得到的目标朝向的 quaternion 等于初始朝向与要执行的旋转的乘积。

在我们的脚本中,要执行的旋转是 deltaAngle,但它是以度为单位表示的,因此我们需要将其转换为 Quaternion。

幸运的是,Quaternion 类的 Euler 函数正好满足需求:它接受三个参数,即绕 X、Y 和 Z 轴的旋转角度,并返回表示该变换的 quaternion。

如前所述,为了获得目标 quaternion,我们需要将初始 quaternion 与旋转 quaternion 相乘,因此在 Update 中可以写:

Quaternion targetRotation = (transform.rotation * (Quaternion.Euler(0f, 0f, deltaAngle)));

接下来,我们通过将 Quaternion.Slerp 计算得到的 quaternion 赋值给 transform.rotation 来更新对象的朝向:

transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, evaluationTime);

现在我们需要定义 evaluationTime:一个介于 0 和 1 之间的 float 值,用来表示我们在从初始朝向过渡到最终朝向过程中的位置。

首先,在脚本类的开头定义并初始化该变量:

private float evaluationTime;

然后在 Start 方法中写:

evaluationTime = 0f;

之后需要在每一帧中递增 evaluationTime,可以在包含 Slerp 的指令之后写:

evaluationTime += Time.deltaTime;

这当然只是一个示例。我的建议是将 Time.deltaTime 乘以一个变量,并在 Inspector 中实时调整该变量的值,直到获得理想的旋转速度。我在关于 Time.deltaTime 的教程中讨论过这一点。

不过按照这种方式,evaluationTime 会在某个时刻达到 1.0,因为它在每一帧中都会递增,并且没有重置机制。

那么我们应该在什么时候重置它?

问题可以这样提出:我们什么时候准备开始模型的新一轮旋转?

答案是:当模型已经指向 Player,并等待 Player 移动时。

通常我会告诉你,当 Surveillance Camera 模型已经指向 Player 且 Player 保持静止时,deltaAngle 等于 0,因为此时不需要进行旋转;不过对于 float 数值,尤其是在不同单位之间转换的情况下,最好保留一定的误差范围。因此我们规定,当 deltaAngle 的绝对值小于 1f 时,动画结束,并且只要 Player 再次移动,就可以开始新的旋转。

因此,在 Update 方法中,在创建 targetRotation 之前写:

if(Mathf.Abs(deltaAngle) < 1f) evaluationTime = 0f;

然后将接下来的三条指令,也就是目标 quaternion 的定义、使用 Slerp 改变朝向以及 evaluationTime 的递增,放入该 if 语句的 else 代码块中。

保存修改后的脚本,返回 Unity 编辑器,按下 Play 观察结果。在这种情况下,旋转速度完全由 Time.deltaTime 决定。如前所述,可以通过将 Time.deltaTime 乘以一个可调变量来减慢或加快速度。

总结一下:在本教程中,我们学习了如何将旋转角度转换为 Quaternions,以计算表示目标朝向的 Quaternion,然后使用 Slerp 执行更慢、更平滑的旋转。旋转速度可以通过 Time.deltaTime 进行校准,同时保持与运行平台无关。

我们还为 Slerp 定义了重置条件,使得当 Player 静止并准备再次移动时,旋转可以重新开始。

好的,这两个教程就到这里。我们下次再见!

本网站仅用于展示我的部分作品,不具有任何推广或商业目的。请注意,目前我不接受,也不会回复任何定制项目、咨询服务或其他形式的合作请求。


高级隐私策略信息和cookie文件的使用