bevy/release-content/migration-guides/generic-option-parameter.md
Chris Russell 9e2bd8ac18
Generic SystemParam impls for Option and Result (#18766)
# Objective

Provide a generic `impl SystemParam for Option<P>` that uses system
parameter validation. This immediately gives useful impls for params
like `EventReader` and `GizmosState` that are defined in terms of `Res`.
It also allows third-party system parameters to be usable with `Option`,
which was previously impossible due to orphan rules.

Note that this is a behavior change for `Option<Single>`. It currently
fails validation if there are multiple matching entities, but with this
change it will pass validation and produce `None`.

Also provide an impl for `Result<P, SystemParamValidationError>`. This
allows systems to inspect the error if necessary, either for bubbling it
up or for checking the `skipped` flag.

Fixes #12634
Fixes #14949
Related to #18516

## Solution

Add generic `SystemParam` impls for `Option` and `Result`, and remove
the impls for specific types.

Update documentation and `fallible_params` example with the new
semantics for `Option<Single>`.
2025-05-07 18:20:08 +00:00

29 lines
952 B
Markdown

---
title: Generic `Option` Parameter
pull_requests: [18766]
---
`Option<Single<D, F>>` will now resolve to `None` if there are multiple entities matching the query.
Previously, it would only resolve to `None` if there were no entities, and would skip the system if there were multiple.
We have introduced a blanket `impl SystemParam for Option` that resolves to `None` if the parameter is invalid.
This allows third-party system parameters to work with `Option`, and makes the behavior more consistent.
If you want a system to run when there are no matching entities but skip when there are multiple,
you will need to use `Query<D, F>` and call `single()` yourself.
```rust
// 0.16
fn my_system(single: Option<Single<&Player>>) {
}
// 0.17
fn my_system(query: Query<&Player>) {
let result = query.single();
if matches!(r, Err(QuerySingleError(MultipleEntities(_)))) {
return;
}
let single: Option<&Player> = r.ok();
}
```