核心概念

# 内容

## 朝向 Heading

AnimGraph 中，所有代表朝向的角度，单位均为“度 (degree)”，并且角度是相对于角色的。例如，方向为0始终表示角色当前的前进方向。正角度表示向左，负角度则表示向右。

## 复位 Reset

AnimGraph 的节点可以在运行时被复位，这意味着它们会返回到初始状态。例如，如果动画片段节点 (Animation Clip node) 被复位，它将跳回到动画的第一帧 (frame)。复位状态器 (state machine) 将导致其从初始状态 (start state) 变为启动状态 (active state)，即使当前状态没有与其连接的过渡 (transition)。

AnimGraph 中的每个节点 (node) 都可以“复位”其任何子节点，并且要注意，对于正确运作和避免动画出现突然跳动，管理好复位非常重要。一般而言，如果上个 update 处于活动状态，那就不该复位，因为这样做可能会导致动作 (pose) 突然剧烈变化。一般情况下，当节点变为活动状态时，您还是会希望对这些节点进行复位，否则它们可能会处于不理想的状态。

在预览模式或查看重播时，节点在重置时将闪烁橙色。

参数
--

图形 (Graph) 中可以包含任意数量的参数，这些参数是游戏提供给 graph 的值，用于决定播放哪些动画。与主输入面板 (Main Inputs) 中的字段 (field) 不同，参数是特定于该 graph 的。这些参数可以是诸如是否蹲伏 (crouch)、角色当前的生命值、角色持有的武器等内容。

参数有不同类型，并且类型决定了它们的用法：

* **Bool参数**：可以是打开或关闭的。适用于可以切换状态的情况。
* **枚举参数**：可以是几个用户定义的值之一，每个值都可以有一个关联的名称。例如，武器 (weapon) 枚举可以有刀 (kinfe)、手枪 (pistol)、步枪 (rifle) 或霰弹枪 (shotgun) 等值。与整数参数 (Int Parameters) 相比，枚举参数的优点在于它们只能设定有限数量的值，并且这些值在编辑器中使用相同的名称，必须要记住，例如值为2表示步枪等情况。因此更不容易出错。
* **Int参数 (整数)**：可以是任何整数。
* **Float参数 (浮点数)**：可以是任何小数。
* **Vector参数 (矢量)**：由3个浮点数组成。

标签
--

AnimTags 是对先前动画系统中 AnimEvents 的改进，是通知游戏代码某个事件发生的首选方法。虽然 AnimEvents 仍受 AnimGraph 支持以保持兼容性，但 标签 具有几个优点：

* **标签可以有持续时间。**监听器 (listeners) 会收到标签通知的"开始/结束"对，或者作为“触发”，这意味着它没有持续时间。使用 AnimEvents 可以在动画上创建"开始/结束"对，但如果动画在达到结束事件之前被打断，那么游戏代码可能会陷入等待状态。若具有“已开始 (started)”的标签即使它们被中断，也一定会发送结束通知。它们还会自动合并，因此如果一个动画在结尾处有一个标签，而另一个动画在开始处有相同的标签，那么游戏代码将只看到1个“开始/结束”对，而不是2个。标签还可以放在动画以外的其他项目上，例如 State Machine 节点中的状态。
* **标签是有类型的。**AnimEvents 仅通过 ID 进行区分，因此即使它只对特定的一个事件感兴趣，游戏代码也必须监听所有 AnimEvents。通过 AnimTags，游戏代码可以针对它关心的标签类型进行注册监听。因此，例如，声音系统可以注册仅接收来自 graph 中的 Audio 标签的通知。
* **标签可以携带任意类型的数据。**因此，Audio 标签可以带有声音文件，而 Cloth 标签可以具有布料求解器的设置。AnimEvents 只能携带一个字符串 (string) 作为负载，虽然该字符串可以是包含多个设置的 KV3 描述，但该字符串仍然必须被解析为代码可以使用的结构。
* **标签是数据驱动的。**每个 Graph 都可以定义自己的一组唯一标签，无需对代码进行修改。AnimEvents 必须在代码中的定义静态列表中拥有一个唯一条目。随着多年来不断创建了新的事件，这个列表变得越来越庞大，可能有些事件只属于一个项目，但仍会显示在所有其他项目的构建中，从而导致有关未公开项目的泄漏。

## 驱动器 Motors

驱动器 (Motors)负责接收来自游戏或用户的输入，以确定角色应该如何移动，并将其转换成动画图可用于驱动动画选择的格式。例如，AI角色可能使用"Path Motor"（路径驱动器），它会接收来自导航系统的路径，并确保角色沿着该路径移动。而"Player Control Motor"（玩家控制驱动器）则会根据玩家的方向输入（如前进、后退、左右）来控制角色的移动。对于不需要移动的角色，则不需要使用驱动器。

驱动器在动画图的 update 过程中会两次发挥作用：

* 在节点更新之前，它们会处理来自游戏的输入，并将其提供给节点，使得节点可以根据输入进行动画计算。
* 在节点完成更新后，它们会执行必要的修复，以便根据节点更新过程中计算得到的"Root Motion"（根动作）进行修正。

## 根动作 Root Motion

"Root Motion" 是指角色在当前更新周期中在世界中位置上的变化量。它是在逻辑更新的过程中计算出来的，然后传递给游戏，用于检查角色在移动过程中是否与其他物体发生碰撞。因此，graph 计算得到的动作可能并不完全反映角色最终的移动情况。在 graph 中的节点可以自由地操作根动作，以满足不同的需求。例如，"Animation Clip" 节点会根据动画中存储的根动作数据来设置根动作，而"Mover" 节点则会根据 motor 设置的目标速度来生成根动作，以使角色的实际移动与 motor 设定的目标速度相匹配。

## 插值 Interpolation

在 Source 2 引擎中，无论是单人游戏还是多人游戏，都采用了客户端-服务器架构。这意味着游戏的核心逻辑发生在服务器端，然后将结果复制到客户端进行显示和渲染。为了保持服务器的性能开销较低，服务器并不会在每个 tick （计时周期）中更新所有角色：大多数AI角色通常只以约10帧每秒（10fps）的频率进行更新。

为了在客户端上实现平滑的动画效果，当其以高于10fps的帧率进行渲染时，需要使用 Interpolation (网络插值)。

插值是指在两个服务器更新周期之间，客户端对数据进行补间处理，以平滑地从一个状态过渡到另一个状态。为了实现插值，客户端需要获取两次服务器更新之间的数据，因此它需要将动画显示的数据延迟约100毫秒，以等待下一个服务器更新周期的数据到达。这样，客户端就能够使用两次服务器更新的数据来进行插值计算，从而使动画过渡更加平滑。

所以到底什么意思呢？简单来说，对于大多数AI和除了本地玩家以外的所有角色：

* 所有游戏逻辑发生在服务器上。
	+ AnimGraph 中的参数值等只会在服务器上设置，而不会在客户端上设置。因此，如果用客户端录制 AnimGraph，并且参数不是您期望的值，请不要认为有什么问题
* 服务器上的 AnimGraph 每秒只会更新10次（即每100毫秒一次）。
	+ 因此，为了保证正确的显示效果，设计 graph 时不要过度依赖精确的时序。
	+ AnimGraph 的记录在服务器上会显得有些不连续。
* 在客户端上，AnimGraph 每帧更新一次。
	+ 但在客户端上，动画仍然会显示得很平滑，客户端 AnimGraph 会处理不同帧率之间的差异。
* 您在屏幕上看到的动画是100毫秒之前的数据。
	+ 当然，也有一些例外情况，比如VR手部动画和网络预测实体（如本地玩家）
* AnimGraph takes care of networking its state automatically, so don't worry about it unless you're trying to do something fancy
* 对于这些情况，AnimGraph 会自动处理网络状态，所以在大多数情况下，您无需过多担心，除非您尝试做一些复杂的特殊处理。

译者:凯凯
原页面：点击跳转