ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Godot 官方文档解读:AnimationNodeStateMachine——用状态机组织复杂动画过渡

Godot 官方文档解读:AnimationNodeStateMachine——用状态机组织复杂动画过渡 文档教程游戏开发【免费下载链接】godot-docsGodot Engine official documentation项目地址https://gitcode.com/GitHub_Trending/go/godot-docs点击查看免费下载导读AnimationNodeStateMachine是 Godot 动画系统AnimationTree中最核心的节点类型之一它把多个动画状态AnimationRootNode组织成一张图并通过「状态 转移」的范式控制动画切换支持最短路径旅行travel()、自动推进Advance Mode、交叉淡化Cross-fade与嵌套状态机。本文以官方类文档classes/class_animationnodestatemachine.rst为骨架结合tutorials/animation/animation_tree.rst教程与AnimationNodeStateMachinePlayback、AnimationNodeStateMachineTransition、AnimationTree的类文档完整讲解其属性、枚举、方法并给出可运行的 GDScript / C# 示例与底层实现依据。一、概述什么是 AnimationNodeStateMachineAnimationNodeStateMachine继承自AnimationRootNode→AnimationNode→Resource→RefCounted→Object是被AnimationTree使用的一个多状态动画根节点。其核心思想来自有限状态机FSM节点Node图中的每个节点是一个动画状态通常由AnimationRootNode充当例如AnimationNodeAnimation、AnimationNodeBlendTree、AnimationNodeBlendSpace1D/2D甚至另一个AnimationNodeStateMachine。转移Transition节点之间用AnimationNodeStateMachineTransition连接定义切换时机、交叉淡化时间与推进条件。控制转移既可以按配置自动触发也可以通过代码触发代码触发时内部使用最短路径算法在图中寻路。在编辑器中创建AnimationNodeStateMachine后底部面板的AnimationTree标签页会出现一个空的 2D 图默认包含Start与End两个状态。要获得代码控制句柄需要从AnimationTree节点上取出parameters/playback参数得到AnimationNodeStateMachinePlayback对象然后调用它的travel(some_state)等方法var state_machine $AnimationTree.get(parameters/playback) state_machine.travel(some_state)var stateMachine GetNodeAnimationTree(AnimationTree).Get(parameters/playback) as AnimationNodeStateMachinePlayback; stateMachine.Travel(some_state);相关教程使用 AnimationTree。完整的状态机构建流程添加状态、连接转移、配置过渡属性详见教程中的 StateMachine 一节。与 AnimationPlayer 的分工需要特别强调AnimationTree本身不持有动画数据动画资源仍存放在AnimationPlayer中对应 AnimationTree.anim_player 属性。AnimationTree只负责播放控制与过渡运算。连接AnimationPlayer后其播放/过渡相关的部分方法与属性应改由AnimationTree及其节点接管AnimationPlayer只负责动画的增删改编辑。二、核心属性详解AnimationNodeStateMachine共有 3 个属性全部在编辑器的 Inspector 中可见也支持运行时读写属性类型默认值作用allow_transition_to_selfboolfalse是否允许travel()瞬移回自身状态reset_endsboolfalse进入 Start/End 节点时是否与 RESET 动画混合state_machine_typeStateMachineType0ROOT状态机的运行类型根 / 嵌套 / 分组1. allow_transition_to_self为true时允许通过AnimationNodeStateMachinePlayback.travel()传送到自身状态若travel()的reset选项开启动画会重新从头播放。为false时传送到自身状态不会发生任何事。典型场景在某个状态内希望“打断重播”当前动画如攻击动作被再次触发可开启此选项并配合travel()的 reset 参数使用。2. reset_ends为true时进入 Start/End 节点的交叉淡化被当作与RESET动画的混合来处理。为false时在大多数情况下若父级AnimationNode还会进行额外的交叉淡化建议关闭本项并让父级节点的交叉淡化时间与状态机的 Start 节点、End 节点匹配可获得更好的混合效果。背后的原理与「确定性混合deterministic blending」相关当两个动画混合时缺失的属性轨道会被视为具有初始值Position/Rotation/Scale 轨道对Skeleton3D骨骼而言初始值为 Bone Rest其他属性初始值为0若该轨道存在于RESET动画中则取其首个关键帧值详见 动画混合指南 中 For better blending 一节。3. state_machine_type该属性通过StateMachineType枚举定义不同使用场景下的转移处理方式是决定状态机“身份”的关键开关详见下文枚举章节。三、StateMachineType 枚举三种状态机类型enum StateMachineType是AnimationNodeStateMachine最重要的枚举取值如下STATE_MACHINE_TYPE_ROOT 0默认寻找到开头seeking to the beginning被当作从起始状态开始播放。转移到结束状态被当作退出状态机。这是最常用的独立状态机类型AnimationTree的根节点通常就是它。STATE_MACHINE_TYPE_NESTED 1寻找到开头被当作寻找到当前状态下动画的开头。转移到结束状态、或某状态没有任何转移时被当作退出状态机。适合作为父状态机内部的“子状态机”但比 GROUPED 更独立它在没有外部父状态机时也能工作。STATE_MACHINE_TYPE_GROUPED 2这是一个分组状态机必须由父级状态机控制不能独立工作。其祖先链中必须存在一个state_machine_type为ROOT或NESTED的状态机。GROUPED 状态机通常与AnimationNodeStateMachinePlayback的信号透传配合使用当分组状态机内的状态启动/结束时其信号会以“分组名 状态名”的前缀形式传递给父级见AnimationNodeStateMachinePlayback的state_started/state_finished信号文档。四、图形管理方法 API 全览AnimationNodeStateMachine提供了 20 个方法用于在代码中动态增删节点与转移、读取/设置坐标供编辑器显示。这些方法把「状态机图」当成一张可编程的图数据结构来操作节点管理方法说明add_node(name, node, position Vector2(0, 0))向图中添加新动画节点position仅用于编辑器显示get_node(name)按名称返回动画节点get_node_list()返回所有节点名称的Array[StringName]get_node_name(node)返回指定节点实例的名称has_node(name)判断图中是否包含指定名称的节点rename_node(name, new_name)重命名节点remove_node(name)从图中删除节点replace_node(name, node)用新节点替换指定名称的节点保留原连接结构转移管理方法说明add_transition(from, to, transition)在两个节点之间添加一条AnimationNodeStateMachineTransitionhas_transition(from, to)判断两个节点之间是否存在转移get_transition_count()返回图中转移的总数get_transition(idx)按下标返回转移对象get_transition_from(idx)/get_transition_to(idx)返回指定下标转移的起始 / 目标节点名remove_transition(from, to)删除两个节点之间的转移remove_transition_by_index(idx)按下标删除转移编辑器辅助坐标get_graph_offset()/set_graph_offset(offset)读取 / 设置整张图的绘制偏移。get_node_position(name)/set_node_position(name, position)读取 / 设置单个节点的坐标。上述坐标与偏移相关 API 的用途是编辑器中的可视排布节点本身在运行时的逻辑连接只取决于转移与坐标无关。这保证了同一张状态机图可以作为Resource被多个场景实例共享教程中强调动画节点是资源直接改节点值会影响所有使用该AnimationTree的实例实例化参数应通过AnimationTree的 Parameters 属性访问。五、转移对象AnimationNodeStateMachineTransition转移是状态机的“动力来源”定义在独立的 AnimationNodeStateMachineTransition 类中。travel()生成的路径严格受限于由AnimationNodeStateMachineTransition连接起来的节点。其关键属性属性默认值说明advance_mode1ENABLED转移的推进模式advance_condition自动推进条件布尔参数名advance_expression自动推进表达式任意表达式break_loop_at_endfalse循环动画在循环末尾是否强制断开以触发转移priority1优先级数值越低越优先被travel()选用resettrue切换到目标状态时是否从头播放switch_mode0IMMEDIATE切换类型xfade_time0.0交叉淡化时间秒xfade_curve—交叉淡化使用的单位Curve缓动曲线SwitchMode三种切换方式值名称行为0SWITCH_MODE_IMMEDIATE立即切换到下一状态当前状态结束并淡入新状态开头1SWITCH_MODE_SYNC立即切换但把新状态对齐到旧状态的播放位置2SWITCH_MODE_AT_END等待当前状态播放结束再切换到下一状态开头AdvanceMode三种推进模式值名称行为0ADVANCE_MODE_DISABLED不使用该转移1ADVANCE_MODE_ENABLED仅在travel()时使用2ADVANCE_MODE_AUTO当advance_condition与advance_expression若已设置为真时自动使用Advance Condition 与 Advance Expression这是状态机自动转移的核心配置教程中有完整讲解Advance Condition一个真/假检查。填入自定义变量名后当状态机到达该转移时会检查该变量是否为true。注意它只能检查真值不能检查假值因此无法表达“变量为 false 才转移”的逻辑例如填入!is_idle不会生效。Advance ExpressionGodot 4 新增用于评估任意表达式等价于if语句中的条件支持如is_walking、is_walking true、is_walking !is_idle、velocity 0、player.is_on_floor()等写法由 Godot 的Expression类求值。# advance_condition 在 AnimationTree 上生成布尔参数可从代码控制 $animation_tree.set(parameters/conditions/idle, is_on_floor and (linear_velocity.x 0))GetNodeAnimationTree(animation_tree).Set(parameters/conditions/idle, IsOnFloor (LinearVelocity.X 0));使用时需注意两点教程明确警告表达式区分大小写引用引擎属性如CharacterBody3D上的velocity用snake_case引用脚本属性则匹配脚本风格GDScript 为snake_caseC# 为PascalCase。使用 Advance Expression 时需要把AnimationTree的Advance Expression Base Node属性指向包含动画变量的脚本所在节点默认为AnimationTree自身。从源码结构看Advance Condition 会成为AnimationTree上的公开参数教程指出 Conditions 位于 Parameters 下而 Advance Expression 因求值基节点在外部脚本中不会出现在 Parameters 列表中。其他转移属性细节xfade_time交叉淡化时长。注意状态机在淡化开始后立即切换当前状态精确剩余时间只能由主动画推断且xfade_time不会被下游 delta 缩放参考AnimationNodeOneShot.fadeout_time的说明。xfade_curve应使用单位区间unitCurve用于替代线性混合获得更细腻的淡化曲线。priority数值越低越优先。在travel()与ADVANCE_MODE_AUTO中都会优先选择低优先级转移。break_loop_at_end即使动画是循环的也允许在循环周期结束时断开以执行转移。另外该类提供advance_condition_changed信号在advance_condition被修改时发出。六、代码控制AnimationNodeStateMachinePlayback状态机的运行时控制不直接操作AnimationNodeStateMachine而是通过从AnimationTree取出parameters/playback得到 AnimationNodeStateMachinePlayback 对象var state_machine $AnimationTree.get(parameters/playback)主要方法方法说明travel(to_node, reset_on_teleport true)沿最短路径从当前状态转移到目标状态若无连通路径则瞬移过去reset_on_teleport控制瞬移时是否从头播放start(node, reset true)直接开始播放指定状态resettrue时从头播放stop()停止当前动画next()若存在 travel 或 auto advance 的下一路径立即切换到下一状态is_playing()当前是否在播放get_current_node()当前播放的状态名注意交叉淡化一旦开始当前状态立即变为下一状态get_current_play_position()/get_current_length()当前状态内的播放位置 / 状态长度get_travel_path()返回 A* 算法内部计算出的当前旅行路径get_fading_from_node()正在淡出的起始状态名get_fading_length()/get_fading_position()当前淡化的总时长 / 淡化进度位置get_fading_from_length()/get_fading_from_play_position()淡出状态的剩余长度 / 播放位置无淡化时返回0信号state_started(state)状态开始播放时发出。state_finished(state)状态播放结束时发出若有交叉淡化则在淡出动画的影响完全消失后触发。若state是 GROUPED 分组状态机其信号会以「分组名 状态名」前缀透传。travel 的底层机制travel()是状态机最强大的能力它让图从当前状态出发沿途经过所有中间状态到达目标状态寻路基于A* 算法教程原文This is done via the A* algorithm。get_travel_path()可以直接返回该路径。若当前状态与目标状态之间不存在连通路径则图会瞬移到目标状态——此时可通过travel()的reset_on_teleport参数决定是否从头播放。使用 travel 的前置条件状态机必须先处于运行状态——要么调用start()要么把某个状态连接到Start节点。var state_machine animation_tree[parameters/playback] state_machine.travel(SomeState)AnimationNodeStateMachinePlayback stateMachine (AnimationNodeStateMachinePlayback)animationTree.Get(parameters/playback); stateMachine.Travel(SomeState);注意AnimationNodeStateMachinePlayback的resource_local_to_scene默认为true覆盖Resource基类默认值这意味着每个场景实例拥有独立的播放状态不会互相污染。七、编辑器实操从零搭建一个状态机综合教程内容完整搭建流程如下对应 AnimationTree 教程 的 StateMachine 一节在AnimationTree节点的tree_root属性中创建AnimationNodeStateMachine或直接用Add Node添加。底部面板AnimationTree标签页出现空 2D 图默认含Start与End状态首次创建时即处于此形态。通过右键或工具栏「创建新节点」加号按钮添加状态——可以是AnimationNodeAnimation、BlendSpace、BlendTree甚至另一个 StateMachine嵌套。编辑复杂子节点时点击状态右侧的铅笔图标返回上一级点击左上角Root。点击工具栏「连接节点」带右箭头的连线按钮在两个状态间拖拽创建转移两个状态间可创建两个方向相反的转移。点击转移在 Inspector 中配置Xfade Time、Xfade Curve、Reset、Priority、Switch Mode切换类型、Advance Mode以及Advance Condition/Advance Expression。取回parameters/playback对象用start()/travel()控制运行。[Start] → [Idle] ⇄ [Walk] → [Jump] → [End]典型角色控制示例GDScriptfunc _ready(): state_machine $AnimationTree.get(parameters/playback) state_machine.start(Idle) func _physics_process(delta): if Input.is_action_pressed(move): state_machine.travel(Walk) else: state_machine.travel(Idle)八、常见问题与最佳实践1. travel 不生效先确认状态机已在运行调用了start()或已有状态连接 Start 节点。此外确认目标状态与当前状态之间存在转移路径——无路径时会瞬移表现是动画直接跳变而非沿线播放。2. 自身状态无法重播检查allow_transition_to_self是否开启并确认travel()的 reset 参数为true。3. Advance Condition 无法表达“非”条件Advance Condition 只能检查布尔变量是否为true。需要表达相反条件时要么准备一对互反变量要么改用 Advance Expression如!is_idle。注意表达式大小写敏感。4. 混合结果不一致为保证混合的确定性缺失的属性轨道会被视为具有初始值Skeleton3D骨骼轨道为 Bone Rest其余属性为0存在RESET动画轨道时取其首帧。建议在RESET动画中为参与混合的属性补齐初始关键帧人物模型建议以 T 姿势T-pose导入让 Bone Rest 尽量接近可活动范围中点避免混合时骨骼穿透身体。5. 何时使用 NESTED / GROUPED单一独立状态机使用默认的ROOT。状态机内部再嵌子状态机如“移动”状态内含“走路/跑步”子状态使用NESTED其行为更接近顶层状态机的语义。希望子状态机把自身状态变化透传给父级使用GROUPED并确保祖先存在 ROOT 或 NESTED 状态机。结语AnimationNodeStateMachine将 Godot 的动画过渡从「固定交叉淡化」升级为「图结构 寻路 条件推进」的完整状态机体系。本文覆盖了它的全部属性、枚举与方法并结合AnimationNodeStateMachineTransition、AnimationNodeStateMachinePlayback与 AnimationTree 教程 给出了构建与代码控制的全链路方案。读者可以在此基础上结合AnimationNodeBlendSpace1D/2D、OneShot、TimeSeek 等节点构建角色移动、连招打断、受击反馈等复杂动画逻辑。赞分享文档教程游戏开发【免费下载链接】godot-docsGodot Engine official documentation项目地址https://gitcode.com/GitHub_Trending/go/godot-docs点击查看免费下载相关推荐Godot动画树复杂动画状态管理与过渡控制Godot动画树复杂动画状态管理与过渡控制 在2D游戏开发中角色动画往往是提升游戏体验的关键环节。从简单的站立、行走到复杂的攻击连招、受伤反应有效的动画Croissant核心架构解析四大层次如何简化机器学习数据工作流Croissant核心架构解析四大层次如何简化机器学习数据工作流 Croissant是一个高级机器学习数据集格式它通过四大核心层次元数据、资源、结构和语义go-gin-example灾难恢复数据备份与服务快速恢复策略go gin example灾难恢复数据备份与服务快速恢复策略 你是否曾因服务器故障导致数据丢失而焦头烂额是否担心过意外停机造成业务中断本文将为你详解基于文档教程游戏开发上一篇Defender 被 no-defender 禁用了一条命令恢复 Windows 安全防护下一篇非 Steam 游戏如何远程同乐RemotePlayWhatever 完整联机指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表