Skip to content

Assets as Entities #11266

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 opened this issue Jan 9, 2024 · 6 comments
Open

Assets as Entities #11266

andriyDev opened this issue Jan 9, 2024 · 6 comments
Labels
A-Assets Load files from disk to use for things like images, models, and sounds C-Feature A new feature, making something new possible D-Complex Quite challenging from either a design or technical perspective. Ask for help! S-Needs-Design This issue requires design work to think about how it would best be accomplished X-Contentious There are nontrivial implications that should be thought through

Comments

@andriyDev
Copy link
Contributor

What problem does this solve or what need does it fill?

The current asset system is stored in a single resource Assets. This means we need a bespoke ID system for assets, events to report changes to assets, different patterns for adding/removing assets, etc.

What solution would you like?

We can unify assets more tightly with the ECS by turning assets into entities.

  • Each asset would be an entity holding an Asset<MyAsset> component.
  • AssetIds would just be Entitys (or a wrapper around Entity).
  • Change detection for assets would just be regular component change detection.
  • Looking up an asset would just be a regular entity lookup.
  • Asset lifetimes can be held in an AssetLifetime component. Handles would refer to the same reference count and a system would check for assets with a ref count of 0 to despawn that entity.

Possible issues

  • Adding assets is no longer immediate. It requires calling apply_deferred (although at least we can get the entity ID immediately so this is not too bad of an issue).
  • There's nothing stopping users from making "weird" asset entities. For example, one entity with two different asset types. When should the asset be cleaned up? Technically this is fine since as long as you hold handles to the same AssetLifetime ref count, it doesn't matter the type. Treating the same entity as a mesh and an image would just be 2 references.
  • Users can add asset entities without the corresponding systems to manage them. Today, since pretty much all the handling must go through the Assets resource, it's fairly hard to have unmanaged assets. Does this matter? For example, you can do weird things without the right systems with events (never clearing, for example). This would just be more of that.

What alternative(s) have you considered?

Keep the system the same. The resource approach is very workable and is pretty nice to use. There are great guard rails (the types are very strong) and it's fairly hard to "break" it.

Additional context

This isn't originally my idea, I'm not sure whose it is though. I just remember hearing about this on Discord and wanted to document this.

@andriyDev andriyDev added C-Feature A new feature, making something new possible S-Needs-Triage This issue needs to be labelled labels Jan 9, 2024
@ItsDoot ItsDoot added A-ECS Entities, components, systems, and events A-Assets Load files from disk to use for things like images, models, and sounds and removed S-Needs-Triage This issue needs to be labelled labels Jan 9, 2024
@alice-i-cecile
Copy link
Member

alice-i-cecile commented Jan 9, 2024

For historical context, this was (mostly) originally proposed by @cart, and detailed a bit in #8624.

What about Assets as Entities?

This Bevy Asset V2 proposal implementation initially stored Assets as ECS Entities. Instead of AssetId + the Assets resource it used Entity as the asset id and Asset values were just ECS components. There are plenty of compelling reasons to do this:

  • Easier to inline assets in Bevy Scenes (as they are "just" normal entities + components)
  • More flexible queries: use the power of the ECS to filter assets (ex: Query<Mesh, With>).
  • Extensible. Users can add arbitrary component data to assets.
  • Things like "component visualization tools" work out of the box to visualize asset data.

However Assets as Entities has a ton of caveats right now:

  • We need to be able to allocate entity ids without a direct World reference (aka rework id allocator in Entities ... i worked around this in my prototypes by just pre allocating big chunks of entities)
  • We want asset change events in addition to ECS change tracking ... how do we populate them when mutations can come from anywhere? Do we use Changed queries? This would require iterating over the change data for all assets every frame. Is this acceptable or should we implement a new "event based" component change detection option?
  • Reconciling manually created assets with asset-system managed assets has some nuance (ex: are they "loaded" / do they also have that component metadata?)
  • "how do we handle "static" / default entity handles" (ties in to the Entity Indices discussion: Entity Indices #8319). This is necessary for things like "built in" assets and default handles in things like SpriteBundle.
  • Storing asset information as a component makes it easy to "invalidate" asset state by removing the component (or forcing modifications). Ideally we have ways to lock this down (some combination of Rust type privacy and ECS validation)

In practice, how we store and identify assets is a reasonably superficial change (porting off of Assets as Entities and implementing dedicated storage + ids took less than a day). So once we sort out the remaining challenges the flip should be straightforward. Additionally, I do still have "Assets as Entities" in my commit history, so we can reuse that work. I personally think "assets as entities" is a good endgame, but it also doesn't provide significant value at the moment and it certainly isn't ready yet with the current state of things.

@alice-i-cecile alice-i-cecile added D-Complex Quite challenging from either a design or technical perspective. Ask for help! and removed A-ECS Entities, components, systems, and events labels Jan 9, 2024
@clarfonthey
Copy link
Contributor

Been poking around trying to think of ways to improve Image, and it really feels like components are the way to go, since the different layers of configuration on top of how the image is drawn can just be components instead of all being part of the image asset.

I'm not really sure where we are for accomplishing this, though. It appears that a decent chunk of the mentioned issues are solved now that we have required components, but I'm not entirely sure.

@BenjaminBrienen BenjaminBrienen added S-Needs-Design This issue requires design work to think about how it would best be accomplished X-Contentious There are nontrivial implications that should be thought through labels Oct 18, 2024
@ElliottjPierce
Copy link
Contributor

I know this isn't possible yet, but I have been thinking about this myself and wanted to quickly highlight some things that this would make feasible. They mostly center around Cart's point: "Extensible. Users can add arbitrary component data to assets."

Shiny Possibility 1: For item systems and other similar systems, item data could be kept modular. Storing health, damage, price, element, model, etc in components is much much more elegant that in a monolithic asset struct. This is especially true if modders want to add their own data to an item.

Shiny Possibility 2: Data could be added to assets as they are spawned/added. For example, when a new mesh is added, an AABB component could be attached to it. This could be much faster than generating AABBs when a Mesh is inserted into an entity (as I believe is done now). Many similar performance advantages may exist.

@andriyDev
Copy link
Contributor Author

One thing that worries me about that first idea (@ElliottjPierce) is that it really restricts what we can do with assets in async contexts. My PR #15813 would allow us to use assets in async, but having all the asset data be just directly on an entity would basically make that impossible. I don't think "monolothic" assets are bad since that's kinda how they are loaded today.

I do think adding computed data to assets would be pretty cool though!

@alice-i-cecile
Copy link
Member

I've written a write-up about the principles I think we should follow when doing *-as-entities refactors like this: https://hackmd.io/@bevy/SypE1qZP1l

@ElliottjPierce
Copy link
Contributor

@alice-i-cecile I've written a write-up about the principles I think we should follow when doing *-as-entities refactors like this: https://hackmd.io/@bevy/SypE1qZP1l

That is well written and I completely agree after reading it.

@andriyDev One thing that worries me about that first idea (@ElliottjPierce) is that it really restricts what we can do with assets in async contexts. My PR #15813 would allow us to use assets in async, but having all the asset data be just directly on an entity would basically make that impossible. I don't think "monolothic" assets are bad since that's kinda how they are loaded today.

I hadn't thought about async implications. I think you're right that async should take priority here; that's kinda important.

However, I don't love the idea of monolithic assets still. My primary concern is being able to add arbitrary data (component-like) to arbitrary assets (entity-like). For example, if item types were represented as monolithic assets, and a modder wanted to add a trading mechanic, they should be able to attach price data to assets that represent items. This would be super ergonomic with ECS, but there may be better ways of doing this.

Async should be the higher priority for assets, but if this functionality could work alongside it that would be awesome. I'm no asset expert, so I trust ya'll's opinions. Just throwing it out there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Assets Load files from disk to use for things like images, models, and sounds C-Feature A new feature, making something new possible D-Complex Quite challenging from either a design or technical perspective. Ask for help! S-Needs-Design This issue requires design work to think about how it would best be accomplished X-Contentious There are nontrivial implications that should be thought through
Projects
None yet
Development

No branches or pull requests

6 participants