bevyengine / bevy

A refreshingly simple data-driven game engine built in Rust
https://bevyengine.org
Apache License 2.0
36.66k stars 3.61k forks source link

Assets as Entities #11266

Open andriyDev opened 10 months ago

andriyDev commented 10 months ago

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.

Possible issues

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.

alice-i-cecile commented 10 months ago

For historical context, this was (mostly) originally proposed by @cart, and detailed a bit in https://github.com/bevyengine/bevy/pull/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: https://github.com/bevyengine/bevy/discussions/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.

clarfonthey commented 1 month ago

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.