核心概念
阅读
2023-08-22更新
最新编辑:TrimesS_
阅读:
更新日期:2023-08-22
最新编辑:TrimesS_
内容
朝向 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 会自动处理网络状态,所以在大多数情况下,您无需过多担心,除非您尝试做一些复杂的特殊处理。
译者:凯凯 原页面:点击跳转