bevy-animation について
Bevy 0.19でアニメーションを実装する開発者向けのリファレンススキルです。クリップ、グラフ、イベント、プロシージャルアニメーションを扱い、ブレンド、glTFの読み込み、性能、アニメーションの12原則の適用方法を解説します。
主な機能
- 01ブレンドと加算アニメーショングラフの構築
- 02アニメーションクリップの再生とクロスフェード
- 03クリップのタイムラインイベントの発火
- 04プロシージャルなイージングとカーブの作成
- 05glTF読み込みと性能に関する解説
活用シーン
- 01待機、歩行、走行アニメーションのブレンド
- 02クリップに合わせた足音やエフェクトの発火
- 03AnimationClipを使わないTransformのトゥイーン
- 04Blenderから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)を使って、アイドル/歩行/走行の間をクロスフェードする場合。- ブレンドノード、加算ノード、ウェイト、
AnimationMaskを使って、コードでAnimationGraphを構築する場合。 - クリップのタイムラインからゲームプレイイベント(足音、ヒットボックスの有効化、VFX の合図)を発生させる場合:
#[derive(AnimationEvent)]+clip.add_event_to_target(...)+On<MyEvent>オブザーバー。 AnimationClipを使わずにプロシージャルなトゥイーンを行う場合 —EasingCurve+EaseFunctionまたはCubicSegment::new_bezier_easingを使って、フレームごとにCurveをサンプリングします。- Bevy のキャラクターにアニメーションの基本原則12か条(Thomas & Johnston、1981年)を適用する場合。
- 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か条
4つの principles-*.md リファレンスでは、Thomas & Johnston の12の原則を、Bevy のどのプリミティブで実際に適用するかに基づいて分類しています。概要は次のとおりです。
- イージングとタイミング — ゆっくり始まり、ゆっくり終わる動き、タイミング、予備動作は、
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はプレリュードに含まれていません。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用です。AnimationTargetId::from_name(&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 はありません。パーティクル/FX システムは別個で、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—StandardMaterialのフィールドを対象とするAnimatableCurveによるマテリアルパラメーターのアニメーション(発光のちらつき、アルファフェード)。bevy-custom-assets—AnimationGraphを RON(.animgraph.ron)にシリアライズしてアセットとして読み込む場合のAssetLoaderパターン。bevy-migration-0-18-to-0-19— 永続化されたターゲット ID とモーフターゲットアセットの変更。
コメント
Markdown 対応