移动/游戏
Godot 2D 动画实现(逐帧精灵、剪纸骨骼…
在 Godot 中用 AnimatedSprite2D / AnimationPlayer / AnimationTree / Tween / MultiMeshInstance2D 实现 2D 动画,并需要保证帧同步、状态切换、挤压拉伸与群集性能正确时使用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
Godot 2D 动画实现(逐帧精灵、剪特定
解决思路
- 按场景选型动画节点:孤立的纯逐帧精灵表用 AnimatedSprite2D;需要驱动非视觉属性或方法轨道时升级到 AnimationPlayer;剪纸动画、非视觉同步、音频/粒子用 AnimationPlayer;复杂状态机、混合、运动用 AnimationTree(逻辑图架在 AnimationPlayer 之上);程序化、动态、一次性的 UI/特效 用 Tween;成千上万实体用 MultiMeshInstance2D + Shader。
- 同帧内同时改变动画和精灵属性时走「一帧同步黄金路径」:先设置 `anim.flip_h = dir < 0`,再 `anim.play(&"run")`,紧接着 `anim.advance(0)` 强制立刻应用姿态,否则 play() 要到下一个 process 帧才生效,会产生一帧闪烁。
- 按场景加载对应脚本(强制):单角色/玩家加载 `one_frame_sync_fix.gd`、`animation_state_sync.gd`,可选 `animation_tree_step.gd` / `tween_lifecycle_manager.gd`;帧事件/命中框/音效同步加载 `animation_sync.gd`(配合 AnimationPlayer 方法轨道);挤压拉伸强制加载 `procedural_squash_stretch.gd`;剪纸/IK 肢体加载 `skeleton_2d_rig_helper.gd`;着色器闪烁/溶解加载 `shader_hook.gd`;成千上万蝙蝠/鱼/道具加载 `multimesh_swarm_anim.gd`。
- 按场景明确「不要加载」的脚本:单角色不要加载 `multimesh_swarm_anim.gd`、`gpu_mesh_optimizer.gd`(除非填充率剖析要求);帧事件/挤压拉伸/剪纸场景不要加载群集/MultiMesh 脚本;不要用逐实体的 AnimatedSprite2D / Tween 管理器处理群集。
- 用 `@onready var anim_sprite` 缓存 AnimatedSprite2D 节点引用,不要在 `_physics_process()` 等热路径中走节点查找 getter(速度慢)。
- 循环动画用 `animation_looped` 信号检测循环,非循环动画才用 `animation_finished`;不要用 `animation_finished` 检测循环动画。
- 在片段中途切换动画/skin 且要保留动画进度时,用 `set_frame_and_progress(frame, progress)`,不要直接设置 `frame`(会把 `frame_progress` 重置为 0.0)。
- 每个精灵只保留一个动画权威:要么用 AnimationPlayer,要么用代码驱动的 AnimatedSprite2D,不要混用两者的轨道(会闪烁并产生状态冲突)。
- Tween 生命周期管理:始终把 Tween 赋给变量,创建新 Tween 前对上一个实例调用 `kill()`,防止多个 Tween 争抢同一属性(最后创建者静默获胜);统一走 `tween_lifecycle_manager.gd`。
- 如果 AnimationPlayer 要移动 CharacterBody2D,把 AnimationPlayer 的 callback mode 设为 Physics;不要在 Idle(渲染)帧驱动物理体,否则破坏固定时间步插值并产生卡顿。
- 2D 网格变形效果差时,在 Mesh2D 编辑器中增加关节附近的顶点数,保证顶点密度均衡;不要用纸一样薄的骨架做形变。
- AnimationTree 状态机切换:先调用 `start()` 再调用 `travel()`,并统一走 `animation_tree_step.gd`。
- 采用剪纸 + cel 混合方案:用骨骼驱动身体运动,在子精灵上对 `frame`/`texture` 打关键帧来做手部/脸部切换(变换动画开销低,cel 切换保持美术可控且无需重新绑定)。
- 优化 GPU 填充率:大块透明精灵浪费填充率,改用紧凑的 `MeshInstance2D` 多边形跳过透明 texel,配合 `gpu_mesh_optimizer.gd`。
- 程序化脚部着地 IK:使用 `skeleton_2d_rig_helper.gd` 搭配 SkeletonModification2DTwoBoneIK(含 `procedural_walker_2d.gd` 用 raycast 目标做 TwoBoneIK 踩地)。
- 剥离帧元数据:用 `animation_data_extractor.gd` 的 value/method tracks 把命中框、生成偏移等元数据与 SpriteFrames 视觉解耦。
- 高分辨率精灵表显存管理:用 `sprite_sheet_memory_manager.gd` 做线程化的高分帧注入与卸载,避免 VRAM 峰值。
- 像素过滤与共享 SpriteFrames:通过 preload 保持资源在多个实例间共享,具体做法查官方 2D sprite animation / SpriteFrames 文档。
- 按需渐进披露:只在研究特定 API 时打开官方文档链接;只在把工作路由到相邻领域时才加载 Related Skills,不要预加载整个知识网络。
- 需要深入时按主题查对应深潜资料:信号/帧事件/skin 切换查 `signals-and-frame-events.md`;剪纸绑定与程序化 IK 脚查 `cutout-and-skeletal.md`;GPU 网格/群集/显存流式加载查 `expert-techniques.md`。
适用边界 · 注意事项
- 不要使用 AnimatedTexture——该类已废弃,在现代渲染器中效率极低,未来 Godot 版本可能被移除,改用 AnimatedSprite2D 或 AnimationPlayer。
- 不要把内联的落地/挤压拉伸判断代码片段直接粘贴进代理里(曾出现过 `not is_on_floor() and is_on_floor()` 这种不可能成立的条件),必须使用 `procedural_squash_stretch.gd` 作为唯一来源。
- 不要在群集场景(成千上万实体)使用逐实体的 AnimatedSprite2D 或 Tween 管理器,应改用 MultiMeshInstance2D + Shader。