用途
本技能用于在 Bevy 引擎(目标版本 Bevy 0.20+)中实现动画播放。当某个实体需要播放一个 AnimationClip 时使用本技能。如果需要混合图(blend graph),应使用 bevy-animation-graph;如果涉及 2D 精灵的具体细节,应使用 bevy-2d-animation。
ECS 结构
- 组件:AnimationPlayer 控制播放;AnimatedBy 将目标实体链接到播放器实体;AnimationTargetId 选择应用哪些曲线。
- 资源:AnimationClip 保存 VariableCurve 条目。
- 系统:advance_animations 推进时间;animate_targets 写入曲线;AnimationPlugin 添加动画支持。
- 事件:AnimationEvent 可以从片段触发。关于观察者(observer)的接线方式,需查阅动画文档,本技能仅给出 trait 名称。
播放要素对照
- 谁推进时间:实体上的 AnimationPlayer。
- 片段资源:AnimationGraph 节点内的 AnimationClip。
- 哪个骨骼或字段:AnimationTargetId 加 AnimatedBy。
- 重复:ActiveAnimation::repeat,它设置 RepeatAnimation::Forever。
使用方式
依赖声明:
[dependencies]
bevy = "0.20"
注意:AnimationPlayer::play 接收的是来自 AnimationGraph 的 AnimationNodeIndex,而不是片段句柄。AnimationGraph::from_clip 构建这个单节点图。AnimatedBy 将目标指向播放器实体。AnimationTargetId::from_name 选择该名称对应的曲线。
设置并播放循环动画的示例:
use bevy::animation::{AnimatedBy, AnimationTargetId};
#[derive(Resource)]
struct WalkNode(AnimationNodeIndex);
fn setup_walk(
mut commands: Commands,
mut clips: ResMut<Assets<AnimationClip>>,
mut graphs: ResMut<Assets<AnimationGraph>>,
) {
let clip = clips.add(AnimationClip::default());
let (graph, index) = AnimationGraph::from_clip(clip);
let player = commands
.spawn((
AnimationPlayer::default(),
AnimationGraphHandle(graphs.add(graph)),
))
.id();
commands.spawn((
AnimatedBy(player),
AnimationTargetId::from_name(&Name::new("Hips")),
Transform::default(),
));
commands.insert_resource(WalkNode(index));
}
fn play_loop(mut players: Query<&mut AnimationPlayer>, walk: Res<WalkNode>) {
for mut player in &mut players {
player.play(walk.0).repeat();
}
}
暂停、恢复和跳转作用于该播放器上的所有活动片段:
fn pause_players(mut players: Query<&mut AnimationPlayer>) {
for mut player in &mut players {
player.pause_all();
}
}
fn resume_and_seek(mut players: Query<&mut AnimationPlayer>) {
for mut player in &mut players {
player.resume_all().seek_all_by(0.25);
}
}
停止单个节点,或查询它是否仍处于活动状态,而不影响同一播放器上的其他片段:
fn stop_walk(mut players: Query<&mut AnimationPlayer>, walk: Res<WalkNode>) {
for mut player in &mut players {
if player.is_playing_animation(walk.0) {
player.stop(walk.0);
}
}
}
#[derive(Resource)]
struct WalkNode(AnimationNodeIndex);
缩放播放器上每个活动片段的速度。glTF 文件会作为 AnimationClip 资源加载;该播放器播放持有该片段的图节点:
fn slow_motion(mut players: Query<&mut AnimationPlayer>) {
for mut player in &mut players {
player.adjust_speeds(0.5);
}
}
专家知识要点
目标:Bevy 0.20+。
核心 ECS 类型:Component、Resource、Query、Commands、Startup、Update、Fixed / FixedMain(bevy::time)、.chain()、Plugin、DefaultPlugins、MinimalPlugins。消息与观察者属于一个所有权槽位,其 API 参见 bevy-events-messaging。除非用 .chain() 对冲突的系统排序,否则系统并行运行。
状态所有权:
- 单个实体上的数据:Component,由某个系统通过 Query 修改,运行在 Update 或 FixedMain。
- 整个应用的一个值:Resource,由某个系统修改,在 Startup 插入,然后在读取它的调度中运行。
- 生成:Commands,由生成系统执行,Startup 用于初始世界,之后的调度用于运行时生成。
- 不能竞态的顺序:.chain(),仅作用于被链式的系统,位于同一调度。
- 插件边界:Plugin,build 注册系统与资源,在应用运行之前。
借用规则:两个都可变查询同一组件的系统必须排序(.chain()),或拆分使只有一个写入。不相关的系统保持并行。这是 ECS 页面规则,不是对系统集 API 的猜测。
决策表:
- 需要每实体数据:用 Component + Query,不要用存储在世界之外的普通结构体。
- 需要应用级配置或时钟:用 Resource,不要把值复制到每个实体上。
- 需要稳定的模拟步长:用 FixedMain 和 Fixed 时钟,不要把模拟绑定到原始帧 Update。
- 需要启动生成:在 Startup 中用 Commands,不要从渲染系统生成。
- 需要非共享状态的跨系统通知:使用 bevy-events-messaging 中的消息或观察者槽位,不要在本文件中发明新的事件类型。
- 需要文档集之外的 API:先查官方文档,不要使用编造的 crate 或 API。
加载 references/ecs-ownership.md 可查看所有权表。
禁止事项
- 不要在文档 URL 中固定 /0.20.0/。原因:链接保持指向最新版;0.20 目标只在正文中说明一次。
- 不要从两个未排序的系统可变查询同一组件。原因:除非用 .chain() 排序,调度会并行运行系统。
- 不要在此发明物理、导航、网络或 XR crate。原因:本技能只命名有文档的 Bevy crate 和模块。
- 不要把 AnimationClip 句柄传给 AnimationPlayer::play。原因:play 接收的是用 AnimationGraph::from_clip 构建的图中的 AnimationNodeIndex。
- 不要使用编造的 API 或未命名的第三方 crate 作为选定方案。原因:Bevy 代码保持惯用 ECS,只使用有文档的 Bevy API。
参考
bevy-master 上的库固定版本保持 0.20.0。永久链接保持不带版本。
官方文档:
- Assets - 官方资源目录。未选择第三方 crate。
- Examples - 最新分支上的示例树。
- Animation examples - 播放器、图和 glTF 片段示例。
- ECS - Component、系统、Query、Startup、Update 和 .chain()。
- Plugins - Plugin、DefaultPlugins、MinimalPlugins 和 add_plugins。
相关技能
前置:
- bevy-master - 中枢与调度。
- bevy-ecs-composition - 组件与系统。
互补:
- bevy-animation-graph - 混合而非单一片段。
- bevy-2d-animation - 精灵目标。
- bevy-asset-scenes - 加载片段资源。
下游 / 消费者:
- bevy-animation-graph - 消费片段。
主技能:
- bevy-master - Bevy 路由。