mirror of
https://github.com/bevyengine/bevy
synced 2024-12-23 03:23:20 +00:00
3c41586154
This commit adds two new `WorldQuery` types: `EntityRefExcept` and `EntityMutExcept`. These types work just like `EntityRef` and `EntityMut`, but they prevent access to a statically-specified list of components. For example, `EntityMutExcept<(AnimationPlayer, Handle<AnimationGraph>)>` provides mutable access to all components except for `AnimationPlayer` and `Handle<AnimationGraph>`. These types are useful when you need to be able to process arbitrary queries while iterating over the results of another `EntityMut` query. The motivating use case is *generalized animation*, which is an upcoming feature that allows animation of any component property, not just rotation, translation, scaling, or morph weights. To implement this, we must change the current `AnyOf<(&mut Transform, &mut MorphWeights)>` to instead be `EntityMutExcept<(AnimationPlayer, Handle<AnimationGraph>)>`. It's possible to use `FilteredEntityMut` in conjunction with a dynamically-generated system instead, but `FilteredEntityMut` isn't optimized for the use case of a large number of allowed components coupled with a small set of disallowed components. No amount of optimization of `FilteredEntityMut` produced acceptable performance on the `many_foxes` benchmark. `Query<EntityMut, Without<AnimationPlayer>>` will not suffice either, as it's legal and idiomatic for an `AnimationTarget` and an `AnimationPlayer` to coexist on the same entity. An alternate proposal was to implement a somewhat-more-general `Except<Q, CL>` feature, where Q is a `WorldQuery` and CL is a `ComponentList`. I wasn't able to implement that proposal in a reasonable way, because of the fact that methods like `EntityMut::get_mut` and `EntityRef::get` are inherent methods instead of methods on `WorldQuery`, and therefore there was no way to delegate methods like `get` and `get_mut` to the inner query in a generic way. Refactoring those methods into a trait would probably be possible. However, I didn't see a use case for a hypothetical `Except` with arbitrary queries: `Query<Except<(&Transform, &Visibility), Visibility>>` would just be a complicated equivalent to `Query<&Transform>`, for instance. So, out of a desire for simplicity, I omitted a generic `Except` mechanism. I've tested the performance of generalized animation on `many_foxes` and found that, with this patch, `animate_targets` has a 7.4% slowdown over `main`. With `FilteredEntityMut` optimized to use `Arc<Access>`, the slowdown is 75.6%, due to contention on the reference count. Without `Arc<Access>`, the slowdown is even worse, over 2x. ## Testing New tests have been added that check that `EntityRefExcept` and `EntityMutExcept` allow and disallow access to components properly and that the query engine can correctly reject conflicting queries involving those types. A Tracy profile of `many_foxes` with 10,000 foxes showing generalized animation using `FilteredEntityMut` (red) vs. main (yellow) is as follows: ![Screenshot 2024-09-12 225914](https://github.com/user-attachments/assets/2993d74c-a513-4ba4-85bd-225672e7170a) A Tracy profile of `many_foxes` with 10,000 foxes showing generalized animation using this `EntityMutExcept` (yellow) vs. main (red) is as follows: ![Screenshot 2024-09-14 205831](https://github.com/user-attachments/assets/4241015e-0c5d-44ef-835b-43f78a24e604)
60 lines
1.6 KiB
TOML
60 lines
1.6 KiB
TOML
[package]
|
|
name = "bevy_ecs"
|
|
version = "0.15.0-dev"
|
|
edition = "2021"
|
|
description = "Bevy Engine's entity component system"
|
|
homepage = "https://bevyengine.org"
|
|
repository = "https://github.com/bevyengine/bevy"
|
|
license = "MIT OR Apache-2.0"
|
|
keywords = ["ecs", "game", "bevy"]
|
|
categories = ["game-engines", "data-structures"]
|
|
rust-version = "1.77.0"
|
|
|
|
[features]
|
|
default = ["bevy_reflect"]
|
|
trace = []
|
|
multi_threaded = ["bevy_tasks/multi_threaded", "arrayvec"]
|
|
bevy_debug_stepping = []
|
|
serialize = ["dep:serde"]
|
|
track_change_detection = []
|
|
reflect_functions = ["bevy_reflect", "bevy_reflect/functions"]
|
|
|
|
[dependencies]
|
|
bevy_ptr = { path = "../bevy_ptr", version = "0.15.0-dev" }
|
|
bevy_reflect = { path = "../bevy_reflect", version = "0.15.0-dev", optional = true }
|
|
bevy_tasks = { path = "../bevy_tasks", version = "0.15.0-dev" }
|
|
bevy_utils = { path = "../bevy_utils", version = "0.15.0-dev" }
|
|
bevy_ecs_macros = { path = "macros", version = "0.15.0-dev" }
|
|
|
|
petgraph = "0.6"
|
|
bitflags = "2.3"
|
|
concurrent-queue = "2.4.0"
|
|
fixedbitset = "0.5"
|
|
serde = { version = "1", optional = true, default-features = false }
|
|
thiserror = "1.0"
|
|
nonmax = "0.5"
|
|
arrayvec = { version = "0.7.4", optional = true }
|
|
smallvec = "1"
|
|
|
|
[dev-dependencies]
|
|
rand = "0.8"
|
|
static_assertions = "1.1.0"
|
|
|
|
[[example]]
|
|
name = "events"
|
|
path = "examples/events.rs"
|
|
|
|
[[example]]
|
|
name = "resources"
|
|
path = "examples/resources.rs"
|
|
|
|
[[example]]
|
|
name = "change_detection"
|
|
path = "examples/change_detection.rs"
|
|
|
|
[lints]
|
|
workspace = true
|
|
|
|
[package.metadata.docs.rs]
|
|
rustdoc-args = ["-Zunstable-options", "--generate-link-to-definition"]
|
|
all-features = true
|