Skip to content

Commit 4a084e1

Browse files
BD103JaySprucealice-i-cecile
authored
Migration writing pass 4 (#2088)
Co-authored-by: JaySpruce <[email protected]> Co-authored-by: Alice Cecile <[email protected]>
1 parent 3181a3e commit 4a084e1

21 files changed

+212
-109
lines changed

content/learn/migration-guides/0.15-to-0.16.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ This guide is currently for a __Release Candidate__ and is subject to change as
1212

1313
The most important changes to be aware of this release are:
1414

15-
- Bevy now prefers `Result`s over panicking, as applications can easily recover from `Result`s instead of crashing. As part of this decision, Bevy's error handling capabilities have been significantly improved. (Systems can easily return `Result`s and a new `BevyError` type has been introduced.) Additionally, several panicking functions have been switched to return a result (`Query::single()`) or have been deprecated completely (`Query::many()`).
15+
- Bevy has reworked its error handling to make it easier to handle `Result`s everywhere. As a result, `Query::single` and friends now return results, rather than panicking.
16+
- Bevy's ECS now has built-in one-to-many entity relationships. The existing parent-child hierarchy system has been modified to use these relationships, causing minor breaking changes in entity despawning behavior and how children are added / replaced for a parent entity.
1617

1718
{{ migration_guides(version="0.16") }}
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
The `Dag::graph` method no longer returns a `petgraph` `DiGraph` and instead returns the new `DiGraph` type within `bevy_ecs`. Edge and node iteration methods are provided so conversion to the `petgraph` type should be trivial if required.
1+
Bevy's ECS no longer depends on the `petgraph` crate. As such, usage of `petgraph::graph::DiGraph` has been replaced with `bevy::ecs::schedule::graph::DiGraph`. This mainly affects code that uses the `Dag::graph()` method.
2+
3+
If you require the `petgraph` version of `DiGraph`, you can manually construct it by iterating over all edges and nodes in Bevy's `DiGraph`.

release-content/0.16/migration-guides/16348_Remove_deprecated_component_reads_and_writes.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
The following methods (some removed in previous PRs) are now replaced by `Access::try_iter_component_access`:
1+
The following methods are now replaced by `Access::try_iter_component_access()`:
22

3-
- `Access::component_reads_and_writes`
4-
- `Access::component_reads`
5-
- `Access::component_writes`
3+
- `Access::component_reads_and_writes()`
4+
- `Access::component_reads()`
5+
- `Access::component_writes()`
66

7-
As `try_iter_component_access` returns a `Result`, you’ll now need to handle the failing case (e.g., `unwrap()`). There is currently a single failure mode, `UnboundedAccess`, which occurs when the `Access` is for all `Components` _except_ certain exclusions. Since this list is infinite, there is no meaningful way for `Access` to provide an iterator. Instead, get a list of components (e.g., from the `Components` structure) and iterate over that instead, filtering using `Access::has_component_read`, `Access::has_component_write`, etc.
7+
As `try_iter_component_access()` returns a `Result`, you’ll now need to handle the failing case (e.g. return early from a system). There is currently a single failure mode, `UnboundedAccess`, which occurs when the `Access` is for all `Components` _except_ certain exclusions. Since this list is infinite, there is no meaningful way for `Access` to provide an iterator. Instead, get a list of components (e.g. from the `Components` structure) and iterate over that instead, filtering using `Access::has_component_read()`, `Access::has_component_write()`, etc.
88

9-
Additionally, you’ll need to `filter_map` the accesses based on which method you’re attempting to replace:
9+
Additionally, you’ll need to `filter_map()` the accesses based on which method you’re attempting to replace:
1010

11-
- `Access::component_reads_and_writes` -> `Exclusive(_) | Shared(_)`
12-
- `Access::component_reads` -> `Shared(_)`
13-
- `Access::component_writes` -> `Exclusive(_)`
11+
|0.15|0.16|
12+
|-|-|
13+
|`Access::component_reads_and_writes()`|`Exclusive(_) | Shared(_)`|
14+
|`Access::component_reads()`|`Shared(_)`|
15+
|`Access::component_writes()`|`Exclusive(_)`|
1416

1517
To ease migration, please consider the below extension trait which you can include in your project:
1618

@@ -74,4 +76,4 @@ impl<T: SparseSetIndex> AccessCompatibilityExt for Access<T> {
7476
}
7577
```
7678

77-
Please take note of the use of `expect(...)` in these methods. You should consider using these as a starting point for a more appropriate migration based on your specific needs.
79+
Please take note of the use of `expect()` in this code. You should consider using this as a starting point for a more appropriate migration based on your specific needs.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
- exchange `Entities::flush_and_reserve_invalid_assuming_no_entities` for `reserve` and `flush_as_invalid` and notify us if that’s insufficient
1+
`Entities::flush_and_reserve_invalid_assuming_no_entities()` was a specialized method primarily used in 0.14 and earlier's rendering world design. With 0.15, `flush_and_reserve_invalid_assuming_no_entities()` went unused, so it now has been removed. If you previously required this method, you should switch to calling `Entities::reserve_entities()` and `Entities::flush_as_invalid()`.
Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,14 @@
1-
- The following deprecated items were removed: `Events::get_reader`, `Events::get_reader_current`, `ManualEventReader`, `Condition::and_then`, `Condition::or_else`, `World::,many_entities`, `World::many_entities_mut`, `World::get_many_entities`, `World::get_many_entities_dynamic`, `World::get_many_entities_mut`, `World::get_many_entities_dynamic_mut`, `World::get_many_entities_from_set_mut`
1+
The following `bevy::ecs` items that were deprecated in 0.15 have been removed:
2+
3+
- `Events::get_reader()`
4+
- `Events::get_reader_current()`
5+
- `ManualEventReader`
6+
- `Condition::and_then()`
7+
- `Condition::or_else()`
8+
- `World::many_entities()`
9+
- `World::many_entities_mut()`
10+
- `World::get_many_entities()`
11+
- `World::get_many_entities_dynamic()`
12+
- `World::get_many_entities_mut()`
13+
- `World::get_many_entities_dynamic_mut()`
14+
- `World::get_many_entities_from_set_mut()`
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
`DeferredWorld::trigger` no longer takes a generic argument. They type is inferred via `impl Event` instead of `T: Event`. If rust can not infer the type for you, consider specifying the type on the variable passed into the function rather than on the function itself.
1+
In 0.15 `DeferredWorld::trigger()` had an unused generic parameter that did not affect the type of the trigger event, so it has been removed.
Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
1+
Several commands have been refactored to internally use closures instead of individual structs, and their structs have been removed.
2+
13
If you were queuing the structs of hierarchy-related commands directly, you will need to change them to methods implemented on `EntityCommands`:
24

3-
| Struct | Method |
4-
|--------------------------------------------------------------|------------------------------------------------------------------------------------------------|
5-
| `commands.queue(AddChild { child, parent })` | `commands.entity(parent).add_child(child)` OR `commands.entity(child).insert(ChildOf(parent))` |
6-
| `commands.queue(AddChildren { children, parent })` | `commands.entity(parent).add_children(children)` |
7-
| `commands.queue(InsertChildren { children, parent, index })` | `commands.entity(parent).insert_children(index, children)` |
8-
| `commands.queue(RemoveChildren { children, parent })` | `commands.entity(parent).remove_children(children)` |
9-
| `commands.queue(ReplaceChildren { children, parent })` | `commands.entity(parent).replace_children(children)` |
10-
| `commands.queue(ClearChildren { parent })` | `commands.entity(parent).remove::<Children>()` |
11-
| `commands.queue(RemoveParent { child })` | `commands.entity(child).remove::<ChildOf>()` |
12-
| `commands.queue(DespawnRecursive { entity, warn: true })` | `commands.entity(entity).despawn()` |
13-
| `commands.queue(DespawnRecursive { entity, warn: false })` | `commands.entity(entity).try_despawn()` |
14-
| `commands.queue(DespawnChildrenRecursive { entity, warn })` | `commands.entity(entity).despawn_related::<Children>()` |
5+
|Struct|Method|
6+
|-|-|
7+
|`commands.queue(AddChild { child, parent })`|`commands.entity(parent).add_child(child)` OR `commands.entity(child).insert(ChildOf(parent))`|
8+
|`commands.queue(AddChildren { children, parent })`|`commands.entity(parent).add_children(children)`|
9+
|`commands.queue(InsertChildren { children, parent, index })`|`commands.entity(parent).insert_children(index, children)`|
10+
|`commands.queue(RemoveChildren { children, parent })`|`commands.entity(parent).remove_children(children)`|
11+
|`commands.queue(ReplaceChildren { children, parent })`|`commands.entity(parent).replace_children(children)`|
12+
|`commands.queue(ClearChildren { parent })`|`commands.entity(parent).remove::<Children>()`|
13+
|`commands.queue(RemoveParent { child })`|`commands.entity(child).remove::<ChildOf>()`|
14+
|`commands.queue(DespawnRecursive { entity, warn: true })`|`commands.entity(entity).despawn()`|
15+
|`commands.queue(DespawnRecursive { entity, warn: false })`|`commands.entity(entity).try_despawn()`|
16+
|`commands.queue(DespawnChildrenRecursive { entity, warn })`|`commands.entity(entity).despawn_related::<Children>()`|
1517

1618
If you were queuing the structs of event-related commands directly, you will need to change them to methods implemented on `Commands`:
1719

18-
| Struct | Method |
19-
|---------------------------------------------------|--------------------------------------------|
20-
| `commands.queue(SendEvent { event })` | `commands.send_event(event)` |
21-
| `commands.queue(TriggerEvent { event, targets })` | `commands.trigger_targets(event, targets)` |
20+
|Struct|Method|
21+
|-|
22+
|`commands.queue(SendEvent { event })`|`commands.send_event(event)`|
23+
|`commands.queue(TriggerEvent { event, targets })`|`commands.trigger_targets(event, targets)`|
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
- `EntityMutExcept` can no-longer be cloned, as this violates Rusts memory safety rules.
1+
`EntityMutExcept` can no-longer be cloned, as doing so violates Rust's memory safety rules.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
The errors `EntityFetchError::NoSuchEntity` and `QueryEntityError::NoSuchEntity` now contain an `EntityDoesNotExistDetails` struct instead of an `UnsafeWorldCell`. If you were just printing these, they should work identically.
1+
`EntityFetchError` enum has been renamed to `EntityMutableFetchError`, and its `NoSuchEntity` variant has been renamed to `EntityDoesNotExist`. Furthermore, the `EntityDoesNotExist` variant now contains an `EntityDoesNotExistError` type, which provides further details on the entity that does not exist.
Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,23 @@
1-
The `Event` trait no longer requires the `Component` trait. If you were relying on this behavior, change your trait bounds from `Event` to `Event + Component`. If you also want your `Event` type to implement `Component`, add a derive.
1+
In 0.15 the `Event` trait required the `Component` trait. This bound has been removed, as it was deemed confusing for users (events aren't typically attached to entities or queried in systems).
2+
3+
If you require an event to implement `Component` (which usually isn't the case), you may manually derive it and update your trait bounds.
4+
5+
```rust
6+
// 0.15
7+
#[derive(Event)]
8+
struct MyEvent;
9+
10+
fn handle_event_component<T: Event>(event_component: T) {
11+
// Access some `Component`-specific property of the event.
12+
let storage_type = T::STORAGE_TYPE;
13+
}
14+
15+
// 0.16
16+
#[derive(Event, Component)]
17+
struct MyEvent;
18+
19+
fn handle_event_component<T: Event + Component>(event_component: T) {
20+
// Access some `Component`-specific property of the event.
21+
let storage_type = T::STORAGE_TYPE;
22+
}
23+
```

0 commit comments

Comments
 (0)