mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 04:33:37 +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},
|
||||
};
|
||||
|
||||
use bevy_asset::Handle;
|
||||
use bevy_derive::{Deref, DerefMut};
|
||||
use bevy_ecs::{
|
||||
component::Component,
|
||||
world::{EntityMutExcept, Mut},
|
||||
};
|
||||
use bevy_ecs::{component::Component, world::Mut};
|
||||
use bevy_math::{Quat, Vec3};
|
||||
use bevy_reflect::{FromReflect, GetTypeRegistration, Reflect, TypePath, Typed};
|
||||
use bevy_render::mesh::morph::MorphWeights;
|
||||
|
@ -18,9 +14,8 @@ use bevy_transform::prelude::Transform;
|
|||
|
||||
use crate::{
|
||||
animatable,
|
||||
graph::AnimationGraph,
|
||||
prelude::{Animatable, GetKeyframe},
|
||||
AnimationEvaluationError, AnimationPlayer, Interpolation,
|
||||
AnimationEntityMut, AnimationEvaluationError, Interpolation,
|
||||
};
|
||||
|
||||
/// 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>(
|
||||
&self,
|
||||
transform: Option<Mut<'a, Transform>>,
|
||||
entity: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
||||
entity: AnimationEntityMut<'a>,
|
||||
weight: f32,
|
||||
) -> Result<(), AnimationEvaluationError>;
|
||||
|
||||
|
@ -185,7 +180,7 @@ pub trait Keyframes: Reflect + Debug + Send + Sync {
|
|||
fn apply_tweened_keyframes<'a>(
|
||||
&self,
|
||||
transform: Option<Mut<'a, Transform>>,
|
||||
entity: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
||||
entity: AnimationEntityMut<'a>,
|
||||
interpolation: Interpolation,
|
||||
step_start: usize,
|
||||
time: f32,
|
||||
|
@ -285,7 +280,7 @@ impl Keyframes for TranslationKeyframes {
|
|||
fn apply_single_keyframe<'a>(
|
||||
&self,
|
||||
transform: Option<Mut<'a, Transform>>,
|
||||
_: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
||||
_: AnimationEntityMut<'a>,
|
||||
weight: f32,
|
||||
) -> Result<(), AnimationEvaluationError> {
|
||||
let mut component = transform.ok_or_else(|| {
|
||||
|
@ -301,7 +296,7 @@ impl Keyframes for TranslationKeyframes {
|
|||
fn apply_tweened_keyframes<'a>(
|
||||
&self,
|
||||
transform: Option<Mut<'a, Transform>>,
|
||||
_: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
||||
_: AnimationEntityMut<'a>,
|
||||
interpolation: Interpolation,
|
||||
step_start: usize,
|
||||
time: f32,
|
||||
|
@ -340,7 +335,7 @@ impl Keyframes for ScaleKeyframes {
|
|||
fn apply_single_keyframe<'a>(
|
||||
&self,
|
||||
transform: Option<Mut<'a, Transform>>,
|
||||
_: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
||||
_: AnimationEntityMut<'a>,
|
||||
weight: f32,
|
||||
) -> Result<(), AnimationEvaluationError> {
|
||||
let mut component = transform.ok_or_else(|| {
|
||||
|
@ -356,7 +351,7 @@ impl Keyframes for ScaleKeyframes {
|
|||
fn apply_tweened_keyframes<'a>(
|
||||
&self,
|
||||
transform: Option<Mut<'a, Transform>>,
|
||||
_: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
||||
_: AnimationEntityMut<'a>,
|
||||
interpolation: Interpolation,
|
||||
step_start: usize,
|
||||
time: f32,
|
||||
|
@ -395,7 +390,7 @@ impl Keyframes for RotationKeyframes {
|
|||
fn apply_single_keyframe<'a>(
|
||||
&self,
|
||||
transform: Option<Mut<'a, Transform>>,
|
||||
_: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
||||
_: AnimationEntityMut<'a>,
|
||||
weight: f32,
|
||||
) -> Result<(), AnimationEvaluationError> {
|
||||
let mut component = transform.ok_or_else(|| {
|
||||
|
@ -411,7 +406,7 @@ impl Keyframes for RotationKeyframes {
|
|||
fn apply_tweened_keyframes<'a>(
|
||||
&self,
|
||||
transform: Option<Mut<'a, Transform>>,
|
||||
_: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
||||
_: AnimationEntityMut<'a>,
|
||||
interpolation: Interpolation,
|
||||
step_start: usize,
|
||||
time: f32,
|
||||
|
@ -454,7 +449,7 @@ where
|
|||
fn apply_single_keyframe<'a>(
|
||||
&self,
|
||||
_: Option<Mut<'a, Transform>>,
|
||||
mut entity: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
||||
mut entity: AnimationEntityMut<'a>,
|
||||
weight: f32,
|
||||
) -> Result<(), AnimationEvaluationError> {
|
||||
let mut component = entity.get_mut::<P::Component>().ok_or_else(|| {
|
||||
|
@ -472,7 +467,7 @@ where
|
|||
fn apply_tweened_keyframes<'a>(
|
||||
&self,
|
||||
_: Option<Mut<'a, Transform>>,
|
||||
mut entity: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
||||
mut entity: AnimationEntityMut<'a>,
|
||||
interpolation: Interpolation,
|
||||
step_start: usize,
|
||||
time: f32,
|
||||
|
@ -536,7 +531,7 @@ impl Keyframes for MorphWeightsKeyframes {
|
|||
fn apply_single_keyframe<'a>(
|
||||
&self,
|
||||
_: Option<Mut<'a, Transform>>,
|
||||
mut entity: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
||||
mut entity: AnimationEntityMut<'a>,
|
||||
weight: f32,
|
||||
) -> Result<(), AnimationEvaluationError> {
|
||||
let mut dest = entity.get_mut::<MorphWeights>().ok_or_else(|| {
|
||||
|
@ -555,7 +550,7 @@ impl Keyframes for MorphWeightsKeyframes {
|
|||
fn apply_tweened_keyframes<'a>(
|
||||
&self,
|
||||
_: Option<Mut<'a, Transform>>,
|
||||
mut entity: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
||||
mut entity: AnimationEntityMut<'a>,
|
||||
interpolation: Interpolation,
|
||||
step_start: usize,
|
||||
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)
|
||||
/// according to the currently-playing animations.
|
||||
pub fn animate_targets(
|
||||
clips: Res<Assets<AnimationClip>>,
|
||||
graphs: Res<Assets<AnimationGraph>>,
|
||||
players: Query<(&AnimationPlayer, &Handle<AnimationGraph>)>,
|
||||
mut targets: Query<(
|
||||
Option<&mut Transform>,
|
||||
EntityMutExcept<(Transform, AnimationPlayer, Handle<AnimationGraph>)>,
|
||||
)>,
|
||||
mut targets: Query<(&AnimationTarget, Option<&mut Transform>, AnimationEntityMut)>,
|
||||
) {
|
||||
// Evaluate all animation targets in parallel.
|
||||
targets
|
||||
.par_iter_mut()
|
||||
.for_each(|(mut transform, mut entity_mut)| {
|
||||
let Some(&AnimationTarget {
|
||||
.for_each(|(target, mut transform, mut entity_mut)| {
|
||||
let &AnimationTarget {
|
||||
id: target_id,
|
||||
player: player_id,
|
||||
}) = entity_mut.get::<AnimationTarget>()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
} = target;
|
||||
|
||||
let (animation_player, animation_graph_id) =
|
||||
if let Ok((player, graph_handle)) = players.get(player_id) {
|
||||
|
|
Loading…
Reference in a new issue