Skip to content
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

Add change ticks to asset references #14444

Open
viridia opened this issue Jul 23, 2024 · 6 comments
Open

Add change ticks to asset references #14444

viridia opened this issue Jul 23, 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

Comments

@viridia
Copy link
Contributor

viridia commented Jul 23, 2024

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

This is something I've run into in my reactive experiments, but it is also directly relevant to @cart 's discussion on next-gen UI. I want to be able to have a reactive context that depends on an Asset, and be able to treat this the same way that I depend on an ECS component or resource. Specifically, given a (possibly type-erased) asset handle, I want to be able to poll for changes using the change tick by comparing it against the current world tick.

Currently assets have an event-based change detection system that is very different from the change detection on components and resources. This difference makes it a challenge to have a unified approach that integrates changes from all the various kinds of data dependencies.

What solution would you like?

The solution that I am considering seems fairly straightforward: within the asset server, the entry which holds an asset (and which asset handles refer to) would add a ticks field, just like components and resources have; and this field would be updated whenever the asset was loaded, reloaded or otherwise changed state. Just as there are APIs for getting the current asset load state, there would be corresponding APIs for getting the change ticks.

I could then use the return value to poll whether an asset had changed.

This new API would not replace the old event-based change detection system, but would augment it.

What alternative(s) have you considered?

I've considered alternate approaches but they are all quite complex and have non-trivial performance impact. For example, one could keep a separate hash map of all asset handles, which then maps to a tick count, and then keep that map up to date by listening to all asset load events. Conversely, one might be able to make a map of only the assets one is interested in, but this requires inventing some kind of "handle-to-a-handle" so that entries from the map can be dropped when there's no longer interest in watching them. Both of these approaches are highly problematic.

Another approach is to copy the asset you want to depend on into a resource, and then have your reactive UI depend on the resource. The obvious problem here is that it introduces considerable extra boilerplate.

@viridia viridia added C-Feature A new feature, making something new possible S-Needs-Triage This issue needs to be labelled labels Jul 23, 2024
@TimJentzsch TimJentzsch added A-UI Graphical user interfaces, styles, layouts, and widgets 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 A-UI Graphical user interfaces, styles, layouts, and widgets labels Jul 24, 2024
@alice-i-cecile
Copy link
Member

Does #5080 solve your needs?

@viridia
Copy link
Contributor Author

viridia commented Jul 28, 2024

It will work but it's not the ideal solution. I need to track assets of different type within the same map; this is easiest if the APIs involve can work in a type-erased manner. Otherwise, each map entry has to be a dyn trait object which wraps the generic data needed to poll the state.

@viridia
Copy link
Contributor Author

viridia commented Jul 28, 2024

Historical note: this was how I handled resources before we added .get_resource_change_ticks_by_id() - basically I had a TrackedResource<R> trait that would poll a given resource for changes. That is no longer needed with the newer API.

@cart
Copy link
Member

cart commented Aug 1, 2024

Worth noting that assets-as-entities would give us this "for free" as assets would be components, which would have change ticks.

@viridia
Copy link
Contributor Author

viridia commented Aug 3, 2024

@cart If assets-as-entities were available today, there are a lot of improvements I could make to my code.

One example is "tabular" assets: my game engine uses a lot of shared, reusable assets which are stored in tables, such that the table is stored in a single file. This means that although the asset is conceptually multiple items, it is loaded as a single Asset; and the granularity of change detection is the entire collection.

My game uses an instanced terrain system where the terrain is made up of modular chunks that can be instanced (I think Diablo does something similar). For loading/performance reasons, I don't store each chunk as a separate asset, but rather a single asset which contains a "contours table". Unfortunately, this means that in the editor, when I edit a terrain chunk, it makes the entire asset as changed, which means that the whole world gets rebuilt - all terrain meshes and flora instances. To get around this, I have to maintain my own change detection / dirty bit system that has a finer granularity, so that individual terrain chunks can be marked as changed.

In an assets-as-entities world, I presume that the collection could be a hierarchy of entities, that is, it could have child entities which have their own separate change bits.

@cart
Copy link
Member

cart commented Aug 5, 2024

In an assets-as-entities world, I presume that the collection could be a hierarchy of entities, that is, it could have child entities which have their own separate change bits.

It would mean that you could have a hierarchy of entities, although whether we embrace that in such a way that the asset loader itself could create that hierarchy / only modify things that have changed is a big open question. I'm thinking we might want to keep it simple / have a one-entity-per-asset model.

My general thought at the moment is:

  1. Embrace the one-entity-per-asset model (much like the current Assets<T> storage where each asset has a single AssetId/type)
  2. Allow developers to (post-asset-load) manually tack on additional components to that asset entity (and/or build hierarchies under it).

But I'm definitely down to discuss how this should work. It is also worth thinking about how sub-assets / labeled assets relate to each other in the context of assets-as-entities (ex: do we support / use entity hierarchies).

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
Projects
None yet
Development

No branches or pull requests

4 participants