-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Assets as entities v0 #22939
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
andriyDev
wants to merge
35
commits into
bevyengine:main
Choose a base branch
from
andriyDev:asset-v1
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Assets as entities v0 #22939
Changes from all commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
24147ff
Implement assets-as-entities.
andriyDev 0488ba3
Reimplement ReflectAsset to take entities into account.
andriyDev a90e545
Migrate most uses of assets within Bevy to assets-as-entities.
andriyDev 4cfd9ab
Update most examples to use assets-as-entities.
andriyDev 20fef63
Fix the asset decompression example to use assets as entities.
andriyDev 7c4e117
Rewrite bevy_text to defer spawning of new atlases until the system e…
andriyDev 3950845
Replace solari's StandardMaterialAssets extraction with a hand-coded …
andriyDev 2463376
Update the error docs to be described in terms of assets-as-entities.
andriyDev 60b5c1d
Add a migration guide.
andriyDev f0c07d8
Create release notes.
andriyDev 0e4e2f2
Delete `asset-mut` migration guide.
andriyDev 0759e81
Send asset events for UUID asset IDs (duplicating their entity's asse…
andriyDev e0817d9
Improve docs on some methods and types.
andriyDev 625eb3c
Merge 'main' branch into asset-v1.
andriyDev 6735834
Fix up migration errors.
andriyDev ac0172f
Add some methods for making it easier to juggle `Assets` and `AssetsM…
andriyDev 2df5388
Migrate `bevy_scene` to use assets-as-entities.
andriyDev 7d3be54
Fix editable_text_system to use the deferred atlases.
andriyDev e0e5a77
Fix up bevy_gizmos_render to use assets-as-entities.
andriyDev 26bbc43
Fix up any new/updated examples.
andriyDev 7ca3759
Merge 'main' branch into 'asset-v1'.
andriyDev 1356f60
More random migrations.
andriyDev 29bbb97
Fix accidentally ambiguous systems after adding Commands (through Ass…
andriyDev 5d15b10
Merge 'main' branch into 'asset-v1'.
andriyDev 29cff47
Fixup bevy_city.
andriyDev 161fa3f
More migrations.
andriyDev bd6fbe8
Replace all `.into()` usages in `spawn_asset` to use `A::from` instead.
andriyDev 3be8021
Implement Deref/DerefMut to deref into the asset type instead of into…
andriyDev a8c86ea
Update accesses to AssetMut and remove triple derefs.
andriyDev 7227e12
Add doc comments for `AssetSelfHandle`.
andriyDev a99ec9c
Fixup doc comments in lib.rs.
andriyDev 05f3a50
Merge 'main' branch into 'asset-v1'.
andriyDev af092aa
Fixup compile errors from merge.
andriyDev 3e238bc
Move migration guide and release notes to _release-content.
andriyDev f6dc2db
Fixup the migration guides.
andriyDev File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
There are no files selected for viewing
195 changes: 195 additions & 0 deletions
195
_release-content/migration-guides/assets_as_entities.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,195 @@ | ||
| --- | ||
| title: Assets-as-entities | ||
| pull_requests: [22939] | ||
| --- | ||
|
|
||
| Previously assets were stored in a resource named `Assets`. Assets are now stored as components on | ||
| entities in the ECS world. This has required us to redesign some of our APIs. Here are some common | ||
| cases and their replacements: | ||
|
|
||
| ## 1. Reading asset data | ||
|
|
||
| - Replace `Res<Assets<A>>` with `Assets<A>`. | ||
|
|
||
| Before: | ||
|
andriyDev marked this conversation as resolved.
|
||
|
|
||
| ```rust | ||
| fn my_system(meshes: Res<Assets<Mesh>>) { | ||
| let handle = ...; | ||
| let data: &Mesh = meshes.get(&handle).unwrap(); | ||
| } | ||
| ``` | ||
|
|
||
| After: | ||
|
|
||
| ```rust | ||
| fn my_system(meshes: Assets<Mesh>) { | ||
| let handle = ...; | ||
| let data: &Mesh = meshes.get(&handle).unwrap(); | ||
| } | ||
| ``` | ||
|
|
||
| ## 2. Mutating asset data | ||
|
|
||
| - Replace `ResMut<Assets<A>>` with `AssetsMut<A>`. | ||
|
|
||
| Before: | ||
|
|
||
| ```rust | ||
| fn my_system(mut meshes: ResMut<Assets<Mesh>>) { | ||
| let handle = ...; | ||
| let data: AssetMut<Mesh> = meshes.get_mut(&handle).unwrap(); | ||
| } | ||
| ``` | ||
|
|
||
| After: | ||
|
|
||
| ```rust | ||
| fn my_system(mut meshes: AssetsMut<Mesh>) { | ||
| let handle = ...; | ||
| let mut data: AssetMut<Mesh> = meshes.get_mut(&handle).unwrap(); | ||
| } | ||
| ``` | ||
|
|
||
| ## 3. Adding new assets | ||
|
|
||
| - Replace `ResMut<Assets<T>>` with `AssetCommands`. | ||
| - For multiple asset types, you only need one `AssetCommands`. | ||
| - Replace `.add()` with `.spawn_asset()`. | ||
| - For types that previously implicitly converted to your type (e.g., `Cuboid` implements | ||
|
andriyDev marked this conversation as resolved.
|
||
| `Into<Mesh>`), you must surround the value in `MyType::from`. | ||
| - If the asset type is "constrained" (e.g., you store the handle into `Handle<Mesh>`), you can | ||
| use `.into()` to convert your value instead. | ||
|
|
||
| Before: | ||
|
|
||
| ```rust | ||
| fn my_system(mut meshes: ResMut<Assets<Mesh>>) { | ||
| // Cuboid gets implicitly converted to Mesh. | ||
| let handle = meshes.add(Cuboid::new(1.0, 2.0, 3.0)); | ||
| } | ||
| ``` | ||
|
|
||
| After: | ||
|
|
||
| ```rust | ||
| fn my_system(mut asset_commands: AssetCommands) { | ||
| let handle = asset_commands.spawn_asset(Mesh::from(Cuboid::new(1.0, 2.0, 3.0))); | ||
| } | ||
| ``` | ||
|
|
||
| Or: | ||
|
|
||
| ```rust | ||
| fn my_system(mut asset_commands: AssetCommands) { | ||
| let handle: Handle<Mesh> = asset_commands.spawn_asset(Cuboid::new(1.0, 2.0, 3.0).into()); | ||
| } | ||
| ``` | ||
|
|
||
| ## 4. Removing assets | ||
|
|
||
| - Replace `ResMut<Assets<A>>` with `AssetCommands`. | ||
| - For multiple asset types, you only need one `AssetCommands`. | ||
| - Replace `.remove()` with `.remove_asset()`. | ||
| - **This does not return the asset**. To get the asset back, you can enqueue a command in | ||
| `Commands`, then use `world.remove_asset()`. | ||
|
|
||
| Before: | ||
|
|
||
| ```rust | ||
| fn my_system(mut meshes: ResMut<Assets<Mesh>>) { | ||
| let handle = ...; | ||
| // We get back the data here. | ||
| let mesh = meshes.remove(&handle).unwrap(); | ||
| } | ||
| ``` | ||
|
|
||
| After: | ||
|
|
||
| ```rust | ||
| fn my_system(mut asset_commands: AssetCommands) { | ||
| let handle = ...; | ||
| // We don't get the data here, since this action is deferred. You need exclusive world access. | ||
| asset_commands.remove(&handle); | ||
| } | ||
| ``` | ||
|
|
||
| ## 5. Spawning materials | ||
|
|
||
| - Since we can no longer deduce the asset type (since we have an untyped `AssetCommands` and | ||
| `MeshMaterial3d` is generic), we need to explicitly convert colors to a material. Wrap your value | ||
| in `StandardMaterial::from` or `ColorMaterial::from` for 3D or 2D respectively. | ||
|
|
||
| Before: | ||
|
|
||
| ```rust | ||
| fn my_system(mut commands: Commands, mut materials: ResMut<Assets<StandardMaterial>>) { | ||
| commands.spawn(( | ||
| Mesh3d(...), | ||
| MeshMaterial3d(materials.add(Color::BLACK)), | ||
| )); | ||
| } | ||
| ``` | ||
|
|
||
| After: | ||
|
|
||
| ```rust | ||
| fn my_system(mut commands: Commands, mut asset_commands: AssetCommands) { | ||
| commands.spawn(( | ||
| Mesh3d(...), | ||
| MeshMaterial3d(asset_commands.spawn_asset(StandardMaterial::from(Color::BLACK))), | ||
| )); | ||
| } | ||
| ``` | ||
|
|
||
| ## 6. UUID assets | ||
|
|
||
| - Instead of accessing the `Assets<A>` resource and inserting the asset into the handle, call | ||
| `world.spawn_uuid_asset()` or `app.world_mut().spawn_uuid_asset()`. | ||
|
|
||
| Before: | ||
|
|
||
| ```rust | ||
| const IMAGE: Handle<Image> = uuid_handle!("1347c9b7-c46a-48e7-b7b8-023a354b7cac"); | ||
|
|
||
| fn my_plugin(app: &mut App) { | ||
| app.world_mut().resource_mut::<Assets<Image>>().insert(&IMAGE, create_some_image()); | ||
| } | ||
| ``` | ||
|
|
||
| After: | ||
|
|
||
| ```rust | ||
| const IMAGE: Handle<Image> = uuid_handle!("1347c9b7-c46a-48e7-b7b8-023a354b7cac"); | ||
|
|
||
| fn my_plugin(app: &mut App) { | ||
| app.world_mut().spawn_uuid_asset(IMAGE.uuid().unwrap(), create_some_image()); | ||
| } | ||
| ``` | ||
|
|
||
| ## Dealing with "deferred" assets | ||
|
|
||
| Some existing code may assume that adding an asset is instant - in other words, you can call | ||
| `Assets::add` and then `Assets::get_mut` to mutate that added asset in the same system. Now that | ||
| assets need to be spawned, calling `AssetCommands::spawn_asset` followed by `AssetsMut::get_mut` | ||
| does not allow you to mutably access the asset. This acts the same way how calling `Commands::spawn` | ||
| followed by `Query::get_mut` does not allow you to mutably access a component. | ||
|
|
||
| There are several ways to deal with this. One possibility is to change your system to be exclusive, | ||
| spawning assets with `DirectAssetAccessExt::spawn_asset`, and mutating the asset with | ||
| `DirectAssetAccessExt::get_asset_mut`. Since these operate on a world, spawning the asset happens | ||
| immediately. | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO we should create an |
||
| Another possibility is to defer the spawning of assets until the end of your system: allow accessing | ||
| an asset either through `AssetsMut` or through a local "pending" collection. Create assets in this | ||
| pending collection instead of spawning them, and then at the end of your system, spawn all pending | ||
| assets. This approach won't work in all cases, but can be straight forward when possible! | ||
|
|
||
| ## Misc changes | ||
|
|
||
| - `Assets::len` -> `Assets::count` | ||
| - `Assets::reserve_handle` -> `AssetCommands::reserve_handle` / `DirectAssetAccessExt::reserve_asset_handle`. | ||
| - `AssetServer::get_id_handle` -> `AssetServer::get_entity_handle` | ||
| - `ReflectAsset::assets_resource_type_id` -> `ReflectAsset::asset_data_type_id` | ||
| - `ReflectAsset::add` -> `ReflectAsset::spawn` | ||
| - `ReflectAsset::len` -> `ReflectAsset::count` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| --- | ||
| title: Assets-as-entities | ||
| authors: ["@andriyDev"] | ||
| pull_requests: [22939] | ||
| --- | ||
|
|
||
| In previous versions of Bevy, assets were stored in a big `Assets` resource (per asset type). | ||
| Continuing our traditions, assets are now represented as entities! This allows us to remove some | ||
| bespoke implementations (like `AssetEvent`) and replace it with more generic ECS features (like | ||
| change detection or hooks/observers). We can now also take advantage of ECS features like | ||
| relationships in the implementation of assets. | ||
|
|
||
| While the simplification of Bevy internals is nice, what's more interesting is how users can | ||
| **also** benefit from these ECS features. For example, users can attach arbitrary components to | ||
| entities, whether that be to extend an asset's data, or to "tag" assets for better observability in | ||
| their apps. While users can take advantage of these today, their usage is still limited (for | ||
| example, users cannot add arbitrary components from within loaders, only from the ECS). We expect | ||
| this API to evolve to bring even more ergonomic access and more features to users! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would really love a regular expression that I can toss into VSCode's find and replace to do this here.