Add docs & example for SystemParam (#1435)

It took me a little while to figure out how to use the `SystemParam` derive macro to easily create my own params. So I figured I'd add some docs and an example with what I learned.

- Fixed a bug in the `SystemParam` derive macro where it didn't detect the correct crate name when used in an example (no longer relevant, replaced by #1426 - see further)
- Added some doc comments and a short example code block in the docs for the `SystemParam` trait
- Added a more complete example with explanatory comments in examples
This commit is contained in:
Wouter Buckens 2021-03-03 03:11:11 +00:00
parent b8a0ab01ba
commit 000dd4c1c2
5 changed files with 68 additions and 0 deletions

View file

@ -260,6 +260,10 @@ path = "examples/ecs/state.rs"
name = "system_chaining"
path = "examples/ecs/system_chaining.rs"
[[example]]
name = "system_param"
path = "examples/ecs/system_param.rs"
[[example]]
name = "timers"
path = "examples/ecs/timers.rs"

View file

@ -338,6 +338,7 @@ struct SystemParamFieldAttributes {
static SYSTEM_PARAM_ATTRIBUTE_NAME: &str = "system_param";
/// Implement `SystemParam` to use a struct as a parameter in a system
#[proc_macro_derive(SystemParam, attributes(system_param))]
pub fn derive_system_param(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);

View file

@ -5,6 +5,25 @@ use crate::{
};
use parking_lot::Mutex;
use std::{any::TypeId, marker::PhantomData, sync::Arc};
/// A parameter that can be used in a system function
///
/// # Derive
/// This trait can be derived.
///
/// ```
/// # use bevy_ecs::prelude::*;
/// use bevy_ecs::SystemParam;
///
/// #[derive(SystemParam)]
/// pub struct MyParam<'a> {
/// foo: Res<'a, usize>,
/// }
///
/// fn my_system(param: MyParam) {
/// // Access the resource through `param.foo`
/// }
/// ```
pub trait SystemParam: Sized {
type Fetch: for<'a> FetchSystemParam<'a>;
}

View file

@ -135,6 +135,7 @@ Example | File | Description
`startup_system` | [`ecs/startup_system.rs`](./ecs/startup_system.rs) | Demonstrates a startup system (one that runs once when the app starts up)
`state` | [`ecs/state.rs`](./ecs/state.rs) | Illustrates how to use States to control transitioning from a Menu state to an InGame state
`system_chaining` | [`ecs/system_chaining.rs`](./ecs/system_chaining.rs) | Chain two systems together, specifying a return type in a system (such as `Result`)
`system_param` | [`ecs/system_param.rs`](./ecs/system_param.rs) | Illustrates creating custom system parameters with `SystemParam`
`timers` | [`ecs/timers.rs`](./ecs/timers.rs) | Illustrates ticking `Timer` resources inside systems and handling their state
## Games

View file

@ -0,0 +1,43 @@
use bevy::{ecs::SystemParam, prelude::*};
/// This example creates a SystemParam struct that counts the number of players
fn main() {
App::build()
.insert_resource(PlayerCount(0))
.add_startup_system(spawn.system())
.add_system(count_players.system())
.run();
}
struct Player;
struct PlayerCount(usize);
/// The SystemParam struct can contain any types that can also be included in a
/// system function signature.
///
/// In this example, it includes a query and a mutable resource.
#[derive(SystemParam)]
pub struct PlayerCounter<'a> {
players: Query<'a, &'a Player>,
count: ResMut<'a, PlayerCount>,
}
impl<'a> PlayerCounter<'a> {
fn count(&mut self) {
self.count.0 = self.players.iter().len();
}
}
/// Spawn some players to count
fn spawn(commands: &mut Commands) {
commands.spawn((Player,));
commands.spawn((Player,));
commands.spawn((Player,));
}
/// The SystemParam can be used directly in a system argument.
fn count_players(mut counter: PlayerCounter) {
counter.count();
println!("{} players in the game", counter.count.0);
}