Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
First pass at simplifying animated_mesh.rs.
Browse files Browse the repository at this point in the history
- Split the setup function in two.
  - One function does the animation setup that we're demonstrating.
  - The other function does the incidental things like spawning the environment.
- Changed the animation playing to use AnimationPlayer directly instead of creating AnimationTransitions.
  - This appears sufficient when only playing a single animation.
  - The animated_mesh_controls example will demonstrate multiple animations and AnimationTransitions.
- Changed the animation asset to be the run cycle.
  - The original animated_fox example used the run.
  - I think this got accidentally changed in bevyengine#17191, so reverting to the original is safest.
- Changed FOX_PATH to a more neutral ASSET_PATH.
- Removed a seemingly redundant AnimationGraphHandle component.
- Added and updated various comments.
greeble-dev committed Jan 9, 2025
1 parent b20e23d commit eb8a95a
Showing 3 changed files with 49 additions and 47 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1289,7 +1289,7 @@ doc-scrape-examples = true

[package.metadata.example.animated_mesh]
name = "Animated Mesh"
description = "Plays an animation from a skinned glTF"
description = "Plays a single animation on a skinned glTF model of a fox"
category = "Animation"
wasm = true

2 changes: 1 addition & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
@@ -194,7 +194,7 @@ Example | Description

Example | Description
--- | ---
[Animated Mesh](../examples/animation/animated_mesh.rs) | Plays an animation from a skinned glTF
[Animated Mesh](../examples/animation/animated_mesh.rs) | Plays a single animation on a skinned glTF model of a fox
[Animated Mesh Control](../examples/animation/animated_mesh_control.rs) | Plays an animation from a skinned glTF with keyboard controls
[Animated Mesh Events](../examples/animation/animated_mesh_events.rs) | Plays an animation from a skinned glTF with events
[Animated Transform](../examples/animation/animated_transform.rs) | Create and play an animation defined by code that operates on the `Transform` component
92 changes: 47 additions & 45 deletions examples/animation/animated_mesh.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
//! Plays animations from a skinned glTF.
use std::{f32::consts::PI, time::Duration};
//! Plays a single animation on a skinned glTF model of a fox.
use bevy::{pbr::CascadeShadowConfigBuilder, prelude::*};
use std::f32::consts::PI;

const FOX_PATH: &str = "models/animated/Fox.glb";
// An example asset that contains a mesh and animation.
const ASSET_PATH: &str = "models/animated/Fox.glb";

fn main() {
App::new()
@@ -14,8 +14,9 @@ fn main() {
..default()
})
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, setup_scene_once_loaded)
.add_systems(Startup, setup_mesh_and_animation)
.add_systems(Startup, setup_environment)
.add_systems(Update, play_animation_once_loaded)
.run();
}

@@ -25,27 +26,58 @@ struct Animations {
index: AnimationNodeIndex,
}

fn setup(
// Create an animation graph and start loading the assets.
fn setup_mesh_and_animation(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
mut graphs: ResMut<Assets<AnimationGraph>>,
) {
// Build the animation graph
// Tell the engine to start loading the asset and spawn it as a scene when
// ready.
commands.spawn(SceneRoot(
asset_server.load(GltfAssetLabel::Scene(0).from_asset(ASSET_PATH)),
));

// Also build an animation graph containing a single animation.
let (graph, index) = AnimationGraph::from_clip(
// We specifically want the "walk" animation, which is the first one.
asset_server.load(GltfAssetLabel::Animation(0).from_asset(FOX_PATH)),
// We want the "run" animation from our example asset, which has an
// index of two.
asset_server.load(GltfAssetLabel::Animation(2).from_asset(ASSET_PATH)),
);

// Keep our animation graph in a Resource so that it can be inserted onto
// the correct entity once the scene actually loads.
// Keep our animation graph in a Resource so that it can be inserted into
// the correct entity once the scene loads.
let graph_handle = graphs.add(graph);
commands.insert_resource(Animations {
graph_handle: graph_handle.clone(),
graph_handle,
index,
});
}

// Detect that the scene is loaded and spawned, then play the animation.
fn play_animation_once_loaded(
mut commands: Commands,
animations: Res<Animations>,
mut players: Query<(Entity, &mut AnimationPlayer), Added<AnimationPlayer>>,
) {
for (entity, mut player) in &mut players {
// Insert the animation graph with our selected animation. This
// connects the animation player to the mesh.
commands
.entity(entity)
.insert(AnimationGraphHandle(animations.graph_handle.clone()));

// Start the animation player and tell it to repeat forever.
player.play(animations.index).repeat();
}
}

// Setup a simple environment with a camera, ground plane, and light.
fn setup_environment(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// Camera
commands.spawn((
Camera3d::default(),
@@ -72,34 +104,4 @@ fn setup(
}
.build(),
));

// Fox
commands.spawn((
SceneRoot(asset_server.load(GltfAssetLabel::Scene(0).from_asset(FOX_PATH))),
AnimationGraphHandle(graph_handle),
));
}

// Once the scene is loaded, start the animation
fn setup_scene_once_loaded(
mut commands: Commands,
animations: Res<Animations>,
mut players: Query<(Entity, &mut AnimationPlayer), Added<AnimationPlayer>>,
) {
for (entity, mut player) in &mut players {
let mut transitions = AnimationTransitions::new();

// Make sure to start the animation via the `AnimationTransitions`
// component. The `AnimationTransitions` component wants to manage all
// the animations and will get confused if the animations are started
// directly via the `AnimationPlayer`.
transitions
.play(&mut player, animations.index, Duration::ZERO)
.repeat();

commands
.entity(entity)
.insert(transitions)
.insert(AnimationGraphHandle(animations.graph_handle.clone()));
}
}

0 comments on commit eb8a95a

Please sign in to comment.