mirror of
https://github.com/bevyengine/bevy
synced 2025-02-16 14:08:32 +00:00
Include AnimationTarget directly in the animation query rather than reading it through the EntityMut (#15413)
# Objective Improve the performance of animation. `animate_targets` only does work for entities with a `AnimationTarget` component, but the query it uses has no filters and matches all archetypes, resulting in extra work checking and ignoring every other entity in the world. In addition, it uses `EntityMutExcept::get`, which has to look up the `ComponentId` for `AnimationTarget` each time it's used. Fixes #15412 ## Solution Instead of `entity_mut.get::<AnimationTarget>()`, add `&AnimationTarget` to the query and read it directly. This requires adding `AnimationTarget` to the list of exceptions in the `EntityMutExcept`. Since the resulting type is getting long, add an alias for it. This does mean that `AnimationTarget` is no longer available through `entity`, which means it's not possible to animate the `AnimationTarget` component itself. ## Testing I ran performance traces of many_foxes comparing this branch to main. Red is main, yellow is these changes: ![image](https://github.com/user-attachments/assets/93ef7d70-5103-4952-86b9-312aafc53e5f)
This commit is contained in:
parent
b04947d44f
commit
2486343e87
2 changed files with 29 additions and 29 deletions
|
@ -5,12 +5,8 @@ use core::{
|
||||||
fmt::{self, Debug, Formatter},
|
fmt::{self, Debug, Formatter},
|
||||||
};
|
};
|
||||||
|
|
||||||
use bevy_asset::Handle;
|
|
||||||
use bevy_derive::{Deref, DerefMut};
|
use bevy_derive::{Deref, DerefMut};
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{component::Component, world::Mut};
|
||||||
component::Component,
|
|
||||||
world::{EntityMutExcept, Mut},
|
|
||||||
};
|
|
||||||
use bevy_math::{Quat, Vec3};
|
use bevy_math::{Quat, Vec3};
|
||||||
use bevy_reflect::{FromReflect, GetTypeRegistration, Reflect, TypePath, Typed};
|
use bevy_reflect::{FromReflect, GetTypeRegistration, Reflect, TypePath, Typed};
|
||||||
use bevy_render::mesh::morph::MorphWeights;
|
use bevy_render::mesh::morph::MorphWeights;
|
||||||
|
@ -18,9 +14,8 @@ use bevy_transform::prelude::Transform;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
animatable,
|
animatable,
|
||||||
graph::AnimationGraph,
|
|
||||||
prelude::{Animatable, GetKeyframe},
|
prelude::{Animatable, GetKeyframe},
|
||||||
AnimationEvaluationError, AnimationPlayer, Interpolation,
|
AnimationEntityMut, AnimationEvaluationError, Interpolation,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A value on a component that Bevy can animate.
|
/// A value on a component that Bevy can animate.
|
||||||
|
@ -154,7 +149,7 @@ pub trait Keyframes: Reflect + Debug + Send + Sync {
|
||||||
fn apply_single_keyframe<'a>(
|
fn apply_single_keyframe<'a>(
|
||||||
&self,
|
&self,
|
||||||
transform: Option<Mut<'a, Transform>>,
|
transform: Option<Mut<'a, Transform>>,
|
||||||
entity: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
entity: AnimationEntityMut<'a>,
|
||||||
weight: f32,
|
weight: f32,
|
||||||
) -> Result<(), AnimationEvaluationError>;
|
) -> Result<(), AnimationEvaluationError>;
|
||||||
|
|
||||||
|
@ -185,7 +180,7 @@ pub trait Keyframes: Reflect + Debug + Send + Sync {
|
||||||
fn apply_tweened_keyframes<'a>(
|
fn apply_tweened_keyframes<'a>(
|
||||||
&self,
|
&self,
|
||||||
transform: Option<Mut<'a, Transform>>,
|
transform: Option<Mut<'a, Transform>>,
|
||||||
entity: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
entity: AnimationEntityMut<'a>,
|
||||||
interpolation: Interpolation,
|
interpolation: Interpolation,
|
||||||
step_start: usize,
|
step_start: usize,
|
||||||
time: f32,
|
time: f32,
|
||||||
|
@ -285,7 +280,7 @@ impl Keyframes for TranslationKeyframes {
|
||||||
fn apply_single_keyframe<'a>(
|
fn apply_single_keyframe<'a>(
|
||||||
&self,
|
&self,
|
||||||
transform: Option<Mut<'a, Transform>>,
|
transform: Option<Mut<'a, Transform>>,
|
||||||
_: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
_: AnimationEntityMut<'a>,
|
||||||
weight: f32,
|
weight: f32,
|
||||||
) -> Result<(), AnimationEvaluationError> {
|
) -> Result<(), AnimationEvaluationError> {
|
||||||
let mut component = transform.ok_or_else(|| {
|
let mut component = transform.ok_or_else(|| {
|
||||||
|
@ -301,7 +296,7 @@ impl Keyframes for TranslationKeyframes {
|
||||||
fn apply_tweened_keyframes<'a>(
|
fn apply_tweened_keyframes<'a>(
|
||||||
&self,
|
&self,
|
||||||
transform: Option<Mut<'a, Transform>>,
|
transform: Option<Mut<'a, Transform>>,
|
||||||
_: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
_: AnimationEntityMut<'a>,
|
||||||
interpolation: Interpolation,
|
interpolation: Interpolation,
|
||||||
step_start: usize,
|
step_start: usize,
|
||||||
time: f32,
|
time: f32,
|
||||||
|
@ -340,7 +335,7 @@ impl Keyframes for ScaleKeyframes {
|
||||||
fn apply_single_keyframe<'a>(
|
fn apply_single_keyframe<'a>(
|
||||||
&self,
|
&self,
|
||||||
transform: Option<Mut<'a, Transform>>,
|
transform: Option<Mut<'a, Transform>>,
|
||||||
_: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
_: AnimationEntityMut<'a>,
|
||||||
weight: f32,
|
weight: f32,
|
||||||
) -> Result<(), AnimationEvaluationError> {
|
) -> Result<(), AnimationEvaluationError> {
|
||||||
let mut component = transform.ok_or_else(|| {
|
let mut component = transform.ok_or_else(|| {
|
||||||
|
@ -356,7 +351,7 @@ impl Keyframes for ScaleKeyframes {
|
||||||
fn apply_tweened_keyframes<'a>(
|
fn apply_tweened_keyframes<'a>(
|
||||||
&self,
|
&self,
|
||||||
transform: Option<Mut<'a, Transform>>,
|
transform: Option<Mut<'a, Transform>>,
|
||||||
_: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
_: AnimationEntityMut<'a>,
|
||||||
interpolation: Interpolation,
|
interpolation: Interpolation,
|
||||||
step_start: usize,
|
step_start: usize,
|
||||||
time: f32,
|
time: f32,
|
||||||
|
@ -395,7 +390,7 @@ impl Keyframes for RotationKeyframes {
|
||||||
fn apply_single_keyframe<'a>(
|
fn apply_single_keyframe<'a>(
|
||||||
&self,
|
&self,
|
||||||
transform: Option<Mut<'a, Transform>>,
|
transform: Option<Mut<'a, Transform>>,
|
||||||
_: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
_: AnimationEntityMut<'a>,
|
||||||
weight: f32,
|
weight: f32,
|
||||||
) -> Result<(), AnimationEvaluationError> {
|
) -> Result<(), AnimationEvaluationError> {
|
||||||
let mut component = transform.ok_or_else(|| {
|
let mut component = transform.ok_or_else(|| {
|
||||||
|
@ -411,7 +406,7 @@ impl Keyframes for RotationKeyframes {
|
||||||
fn apply_tweened_keyframes<'a>(
|
fn apply_tweened_keyframes<'a>(
|
||||||
&self,
|
&self,
|
||||||
transform: Option<Mut<'a, Transform>>,
|
transform: Option<Mut<'a, Transform>>,
|
||||||
_: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
_: AnimationEntityMut<'a>,
|
||||||
interpolation: Interpolation,
|
interpolation: Interpolation,
|
||||||
step_start: usize,
|
step_start: usize,
|
||||||
time: f32,
|
time: f32,
|
||||||
|
@ -454,7 +449,7 @@ where
|
||||||
fn apply_single_keyframe<'a>(
|
fn apply_single_keyframe<'a>(
|
||||||
&self,
|
&self,
|
||||||
_: Option<Mut<'a, Transform>>,
|
_: Option<Mut<'a, Transform>>,
|
||||||
mut entity: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
mut entity: AnimationEntityMut<'a>,
|
||||||
weight: f32,
|
weight: f32,
|
||||||
) -> Result<(), AnimationEvaluationError> {
|
) -> Result<(), AnimationEvaluationError> {
|
||||||
let mut component = entity.get_mut::<P::Component>().ok_or_else(|| {
|
let mut component = entity.get_mut::<P::Component>().ok_or_else(|| {
|
||||||
|
@ -472,7 +467,7 @@ where
|
||||||
fn apply_tweened_keyframes<'a>(
|
fn apply_tweened_keyframes<'a>(
|
||||||
&self,
|
&self,
|
||||||
_: Option<Mut<'a, Transform>>,
|
_: Option<Mut<'a, Transform>>,
|
||||||
mut entity: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
mut entity: AnimationEntityMut<'a>,
|
||||||
interpolation: Interpolation,
|
interpolation: Interpolation,
|
||||||
step_start: usize,
|
step_start: usize,
|
||||||
time: f32,
|
time: f32,
|
||||||
|
@ -536,7 +531,7 @@ impl Keyframes for MorphWeightsKeyframes {
|
||||||
fn apply_single_keyframe<'a>(
|
fn apply_single_keyframe<'a>(
|
||||||
&self,
|
&self,
|
||||||
_: Option<Mut<'a, Transform>>,
|
_: Option<Mut<'a, Transform>>,
|
||||||
mut entity: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
mut entity: AnimationEntityMut<'a>,
|
||||||
weight: f32,
|
weight: f32,
|
||||||
) -> Result<(), AnimationEvaluationError> {
|
) -> Result<(), AnimationEvaluationError> {
|
||||||
let mut dest = entity.get_mut::<MorphWeights>().ok_or_else(|| {
|
let mut dest = entity.get_mut::<MorphWeights>().ok_or_else(|| {
|
||||||
|
@ -555,7 +550,7 @@ impl Keyframes for MorphWeightsKeyframes {
|
||||||
fn apply_tweened_keyframes<'a>(
|
fn apply_tweened_keyframes<'a>(
|
||||||
&self,
|
&self,
|
||||||
_: Option<Mut<'a, Transform>>,
|
_: Option<Mut<'a, Transform>>,
|
||||||
mut entity: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
mut entity: AnimationEntityMut<'a>,
|
||||||
interpolation: Interpolation,
|
interpolation: Interpolation,
|
||||||
step_start: usize,
|
step_start: usize,
|
||||||
time: f32,
|
time: f32,
|
||||||
|
|
|
@ -1094,28 +1094,33 @@ pub fn advance_animations(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A type alias for [`EntityMutExcept`] as used in animation.
|
||||||
|
pub type AnimationEntityMut<'w> = EntityMutExcept<
|
||||||
|
'w,
|
||||||
|
(
|
||||||
|
AnimationTarget,
|
||||||
|
Transform,
|
||||||
|
AnimationPlayer,
|
||||||
|
Handle<AnimationGraph>,
|
||||||
|
),
|
||||||
|
>;
|
||||||
|
|
||||||
/// A system that modifies animation targets (e.g. bones in a skinned mesh)
|
/// A system that modifies animation targets (e.g. bones in a skinned mesh)
|
||||||
/// according to the currently-playing animations.
|
/// according to the currently-playing animations.
|
||||||
pub fn animate_targets(
|
pub fn animate_targets(
|
||||||
clips: Res<Assets<AnimationClip>>,
|
clips: Res<Assets<AnimationClip>>,
|
||||||
graphs: Res<Assets<AnimationGraph>>,
|
graphs: Res<Assets<AnimationGraph>>,
|
||||||
players: Query<(&AnimationPlayer, &Handle<AnimationGraph>)>,
|
players: Query<(&AnimationPlayer, &Handle<AnimationGraph>)>,
|
||||||
mut targets: Query<(
|
mut targets: Query<(&AnimationTarget, Option<&mut Transform>, AnimationEntityMut)>,
|
||||||
Option<&mut Transform>,
|
|
||||||
EntityMutExcept<(Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
|
||||||
)>,
|
|
||||||
) {
|
) {
|
||||||
// Evaluate all animation targets in parallel.
|
// Evaluate all animation targets in parallel.
|
||||||
targets
|
targets
|
||||||
.par_iter_mut()
|
.par_iter_mut()
|
||||||
.for_each(|(mut transform, mut entity_mut)| {
|
.for_each(|(target, mut transform, mut entity_mut)| {
|
||||||
let Some(&AnimationTarget {
|
let &AnimationTarget {
|
||||||
id: target_id,
|
id: target_id,
|
||||||
player: player_id,
|
player: player_id,
|
||||||
}) = entity_mut.get::<AnimationTarget>()
|
} = target;
|
||||||
else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
let (animation_player, animation_graph_id) =
|
let (animation_player, animation_graph_id) =
|
||||||
if let Ok((player, graph_handle)) = players.get(player_id) {
|
if let Ok((player, graph_handle)) = players.get(player_id) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue