|
1 | 1 | <!-- SystemParamBuilder - Support dynamic system parameters --> |
2 | 2 | <!-- https://github.com/bevyengine/bevy/pull/14817 --> |
3 | 3 |
|
4 | | -<!-- TODO --> |
| 4 | +Bevy 0.14 introduced [the `SystemBuilder` type](https://bevyengine.org/news/bevy-0-14/#systembuilder) to allow systems to be created with dynamic queries. |
| 5 | +In Bevy 0.15, this has been extended to many more types of system parameters! |
| 6 | + |
| 7 | +The `SystemBuilder` type has been replaced with a `SystemParamBuilder<P>` trait to make it easier to compose builders. |
| 8 | +Aggregates of parameters, including [tuples, `ParamSet`](https://github.com/bevyengine/bevy/pull/14050), [`Vec<T>`](https://github.com/bevyengine/bevy/pull/14821), and [custom parameters using `#[derive(SystemParam)]`](https://github.com/bevyengine/bevy/pull/14818), can now be used in dynamic systems. |
| 9 | +For example, a `ParamSet<Vec<Query<FilteredEntityMut>>>` can be used to pass a variable number of dynamic queries that may conflict. |
| 10 | + |
| 11 | +New [`FilteredResources` and `FilteredResourcesMut`](https://github.com/bevyengine/bevy/pull/15189) types can access a set of resources configured at runtime, similar to how the existing `FilteredEntityRef` and `FilteredEntityMut` access a set of components on one entity. |
| 12 | + |
| 13 | +Finally, a new [`DynSystemParam`](https://github.com/bevyengine/bevy/pull/14817) type allows systems to use parameters of dynamic type and then downcast them. |
| 14 | +This is especially useful for implementing part of a system with trait objects, where each trait implementation can use a different system parameter type. |
| 15 | + |
| 16 | +Taken together, these can be used to build a system that runs a script defined at runtime, where the script needs a variable number of query and resource parameters. |
| 17 | +Or, they can be used to build systems out of parts assembled at runtime! |
| 18 | + |
| 19 | +```rust |
| 20 | +fn buildable_system( |
| 21 | + query_a: Query<&A>, |
| 22 | + query_b: Query<&B>, |
| 23 | + queries_with_locals: Vec<(Query<FilteredEntityMut>, Local<usize>)>, |
| 24 | + mut dynamic_params: ParamSet<Vec<DynSystemParam>>, |
| 25 | + resources: FilteredResourcesMut, |
| 26 | +) { |
| 27 | + // Parameters in a `ParamSet<Vec>` are accessed by index. |
| 28 | + let mut dyn_param_0: DynSystemParam = dynamic_params.get_mut(0); |
| 29 | + // Parameters in a `DynSystemParam` are accessed by downcasting to the original type. |
| 30 | + let param: Local<&str> = dyn_param_0.downcast_mut::<Local<&str>>().unwrap(); |
| 31 | + // `FilteredResources` and `FilteredResourcesMut` have methods to get resources by type or by ID. |
| 32 | + let res: Ref<R> = resources.get::<R>().unwrap(); |
| 33 | +} |
| 34 | + |
| 35 | +let param_builder = ( |
| 36 | + // Parameters that don't need configuration can be built using `ParamBuilder` or its factory methods. |
| 37 | + ParamBuilder, |
| 38 | + ParamBuilder::query(), |
| 39 | + // A `Vec` of parameters can be built using a `Vec` of builders. |
| 40 | + vec![ |
| 41 | + // A tuple of parameters can be built using a tuple of builders. |
| 42 | + ( |
| 43 | + // Queries are built with a callback that supplies a `QueryBuilder` to configure the query. |
| 44 | + QueryParamBuilder::new(|builder| { builder.data::<&A>(); }), |
| 45 | + // Locals are built by passing the initial value for the local. |
| 46 | + LocalBuilder(123), |
| 47 | + ), |
| 48 | + ], |
| 49 | + // A `ParamSet` can be built for either a tuple or a `Vec`. |
| 50 | + ParamSetBuilder(vec![ |
| 51 | + // A `DynSystemParam` is built using a builder for any type, and can be downcast to that type. |
| 52 | + DynParamBuilder::new(LocalBuilder("hello")), |
| 53 | + DynParamBuilder::new(ParamBuilder::resource::<R>()), |
| 54 | + // The type may be any system parameter, even a tuple or a `Vec`! |
| 55 | + DynParamBuilder::new((ParamBuilder::query::<&A>(), ParamBuilder::query::<&B>())), |
| 56 | + ]), |
| 57 | + // `FilteredResources` and `FilteredResourcesMut` are built with a callback |
| 58 | + // that supplies a builder to configure the resource access. |
| 59 | + FilteredResourcesMutParamBuilder::new(|builder| { builder.add_read::<R>(); }), |
| 60 | +); |
| 61 | + |
| 62 | +let system = param_builder |
| 63 | + .build_state(&mut world) |
| 64 | + .build_system(buildable_system); |
| 65 | + |
| 66 | +// The built system is just like any other system, and can be added to a schedule. |
| 67 | +schedule.add_systems(system); |
| 68 | +``` |
0 commit comments