关于 bevy-animation
面向 Bevy 0.19 开发者的动画实现参考技能,涵盖动画片段、图、事件和程序化运动。提供经过验证的模式,并介绍混合、glTF 导入、性能及动画十二原则的应用。
主要功能
- 01构建混合与叠加动画图
- 02播放并交叉淡入动画片段
- 03触发片段时间线事件
- 04创建程序化缓动与曲线
- 05提供 glTF 导入和性能指导
适用场景
- 01混合待机、行走和奔跑动画
- 02根据动画片段触发脚步或特效
- 03不使用 AnimationClip 对变换进行补间
- 04排查 Blender 到 glTF 的骨骼动画问题
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ chrisgliddon/ bevy-skills --skill bevy-animation安装后在 Claude Code 中输入/bevy-animation确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/animation-events.mdanimation-graph.mdcurves-and-tweening.mdgltf-import.mdperformance.mdprinciples-authoring.mdprinciples-easing-and-timing.mdprinciples-graph-layering.mdprinciples-transform-keyframes.mdprocedural-animation.mdstate-machines.md详细介绍
Bevy 0.19 — 动画(图、混合、事件、12 项原则)
适用场景
- 加载 glTF 动画片段并在角色上播放:
AnimationPlayer+AnimationGraphHandle。 - 通过
AnimationTransitions::play(player, node, Duration)在待机 / 行走 / 奔跑动画之间交叉淡入淡出。 - 在代码中构建
AnimationGraph:混合节点、加法节点、权重、AnimationMask。 - 从动画片段时间线上触发游戏事件(脚步声、碰撞箱激活、VFX 提示):使用
#[derive(AnimationEvent)]+clip.add_event_to_target(...)+On<MyEvent>观察器。 - 在没有
AnimationClip的情况下进行程序化补间——每帧通过EasingCurve+EaseFunction或CubicSegment::new_bezier_easing对Curve采样。 - 将动画 12 项基本原则(Thomas & Johnston,1981)应用于 Bevy 角色。
- 导入 Blender 骨架,发现骨骼没有动画——通常是因为
AnimationTargetId::from_name需要Name。
端到端标准模式
已通过 bevy = "0.19" 验证——bevy-skills-tester/skill-snippets/examples/bevy_animation.rs 中的 cargo check 检查通过。
use bevy::{
animation::{
animated_field,
animation_curves::{AnimatableCurve, AnimatableKeyframeCurve},
AnimationEvent, AnimationTargetId,
},
prelude::*,
};
use core::time::Duration;
#[derive(AnimationEvent, Clone)]
struct FootstepEvent { foot: u8 }
fn setup(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut clips: ResMut<Assets<AnimationClip>>,
mut graphs: ResMut<Assets<AnimationGraph>>,
) {
// 1. Load a glTF clip
let walk: Handle<AnimationClip> =
asset_server.load("models/character.glb#Animation0");
// 2. Build a tiny procedural clip with a sample curve + an event
let bone = AnimationTargetId::from_name(&Name::new("Hips"));
let tween = AnimatableKeyframeCurve::new([
(0.0_f32, Vec3::ZERO),
(0.5, Vec3::new(0.0, 1.0, 0.0)),
(1.0, Vec3::ZERO),
]).expect("strictly-increasing times");
let curve = AnimatableCurve::new(animated_field!(Transform::translation), tween);
let mut proc = AnimationClip::default();
proc.add_curve_to_target(bone, curve);
proc.add_event(0.5, FootstepEvent { foot: 0 });
let proc = clips.add(proc);
// 3. Compose a graph: root → walk + additive(proc, mask=group 0 excluded)
const MASK_GROUP_0_BIT: u64 = 1 << 0;
let mut graph = AnimationGraph::new();
let root = graph.root;
let _walk_node = graph.add_clip(walk, 1.0, root);
let additive = graph.add_additive_blend(0.5, root);
let _proc_node = graph.add_clip_with_mask(proc, MASK_GROUP_0_BIT, 1.0, additive);
// 4. Spawn the player entity (bones come from the loaded glTF scene)
commands.spawn((
Name::new("AnimationRoot"),
AnimationPlayer::default(),
AnimationGraphHandle(graphs.add(graph)),
AnimationTransitions::new(),
));
}
fn start(mut q: Query<(&mut AnimationTransitions, &mut AnimationPlayer), Added<AnimationPlayer>>) {
use bevy::animation::{graph::AnimationNodeIndex, RepeatAnimation};
for (mut tx, mut player) in &mut q {
tx.play(&mut player, AnimationNodeIndex::new(1), Duration::from_millis(250))
.set_repeat(RepeatAnimation::Forever);
}
}
fn on_footstep(trigger: On<FootstepEvent>) {
let foot = trigger.foot; // On<E> derefs to &E
let _entity = trigger.trigger().target; // AnimationEventTrigger::target
let _ = foot;
}
fn main() {
App::new()
.add_plugins(DefaultPlugins) // gltf_animation is a default feature
.add_systems(Startup, setup)
.add_systems(Update, start)
.add_observer(on_footstep)
.run();
}
主题
| 主题 | 参考资料 |
|---|---|
构建混合 / 加法图、AnimationMask、热切换 | references/animation-graph.md |
Blender → glTF → Bevy 导入:Name、坐标轴、多动画片段、不支持的扩展 | references/gltf-import.md |
Update 与 FixedUpdate 中的程序化动画、根运动提取 | references/procedural-animation.md |
待机 / 行走 / 奔跑混合;AnimationTransitions::play 与 Bevy States 集成 | references/state-machines.md |
#[derive(AnimationEvent)]、add_event_to_target、On<E> 观察器连接 | references/animation-events.md |
AnimatableCurve、EasingCurve、EaseFunction、三次贝塞尔、UnevenSampleAutoCurve | references/curves-and-tweening.md |
AnimationPlayer 开销、蒙皮缓冲区、图复杂度、运行时图切换 | references/performance.md |
| 原则 — 缓入 / 缓出、节奏、预备动作 → 缓动 + 时长 | references/principles-easing-and-timing.md |
原则 — 挤压与拉伸、弧线、夸张 → Transform 关键帧 | references/principles-transform-keyframes.md |
| 原则 — 构图、跟随动作、次要动作 → 图分层 + 遮罩 | references/principles-graph-layering.md |
| 原则 — 直线动画与姿势动画、立体绘制、吸引力 → 上游创作 | references/principles-authoring.md |
动画 12 项基本原则
四份 principles-*.md 参考资料按照 Bevy 实际运用的基本构件,对 Thomas & Johnston 提出的 12 项原则进行归类。快速概览:
- 缓动与节奏 — 缓入 / 缓出、节奏、预备动作对应
EaseFunction/EasingCurve/CubicSegment::new_bezier_easing,以及动画片段时长和ActiveAnimation::set_speed。 - Transform 关键帧 — 挤压与拉伸、弧线、夸张通过
animated_field!,对Transform::scale/::translation使用AnimatableKeyframeCurve。 - 图分层 — 构图、跟随动作与重叠动作、次要动作对应
AnimationGraph::add_additive_blend+AnimationMask分组隔离。 - 创作 — 直线动画与姿势动画、立体绘制、吸引力属于 DCC 工具(Blender、Maya)的范畴。Bevy 会播放你创作的内容。
易错点
- 目标组件已拆分。
AnimationTarget { id, player }已不复存在。 骨骼实体使用AnimationTargetId(Uuid)加上AnimatedBy(Entity);glTF 加载器会同时提供这两个组件。 - 重新生成持久化的目标 ID。 Bevy 0.19 更改了
AnimationTargetId的计算算法。必须根据层级/名称路径重新计算从 0.18 序列化的目标 ID。 gltf_animation默认启用。 它已包含在bevy = "0.19"的默认功能中——除非你使用了default-features = false,否则无需选择启用。AnimationTransitions::play_with_transition并不存在。 实际上唯一的方法是play(&mut self, player, node, Duration) -> &mut ActiveAnimation。在返回值上链式调用.set_repeat(RepeatAnimation::Forever)/.set_speed(f32)。animated_field!和AnimatableCurve不在 prelude 中。 请从bevy::animation::{animated_field, animation_curves::{AnimatableCurve, AnimatableKeyframeCurve}}显式导入。On<AnimationEvent>不是EntityEvent观察器。On<E>解引用为&E(可直接访问事件字段)。触发实体位于trigger.trigger().target(AnimationEventTrigger::target字段在 0.18 中由animation_player重命名而来)。不能使用.target()——该方法用于EntityEvent。- 骨骼实体必须包含
Name,这样AnimationTargetId::from_name(&Name)才能解析。glTF 加载器会设置此组件;手动构建的骨架也必须设置。 AnimationMask的位极性。 节点的u64掩码中某个位被置位,意味着该节点不会为该组中的目标设置动画。通过graph.add_target_to_mask_group(target_id, group_u32)将骨骼注册到一个组。若要将节点限制在单个组中,应设置除该组以外的所有位。- 调度。 Bevy 的动画系统在
PostUpdate中运行,并通过.before(TransformSystems::Propagate)链接。也会写入Transform的过程式系统应在Update中运行,或明确指定其相对于PostUpdate中AnimationSystems的顺序。 - 核心动画不涵盖的内容。 不内置 IK,粒子/特效系统是独立的,且 glTF 加载器未实现
KHR_animation_pointer——参见references/gltf-import.md。
另请参阅
bevy-cameras— 摄像机动画(平移、推拉、跟随焦点)与此技能有所重叠;使用相同的EaseFunction/EasingCurve工具集。bevy-core-concepts— 过程式动画中Update与FixedUpdate的选择很重要;参见procedural-animation.md。bevy-ecs-systems— 用于AnimationEvent的观察器连接模式(On<E>、add_observer)。bevy-pbr-materials— 通过AnimatableCurve为StandardMaterial字段设置材质参数动画(自发光闪烁、Alpha 淡变)。bevy-custom-assets— 如果你将AnimationGraph序列化为 RON(.animgraph.ron)并作为资源加载,可参考其中的AssetLoader模式。bevy-migration-0-18-to-0-19— 持久化目标 ID 和变形目标资源的变更。
评论
支持 Markdown