-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
Allow AssetServer::load
to acquire a guard item.
#13051
Conversation
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.
Could you add an example demonstrating how one might use this? This seems like a really neat design, but making the jump from "cool API" to "practical use" has been a perpetual challenge for users of bevy_asset.
The generated |
1 similar comment
The generated |
Added an example to show how this works. |
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.
Okay, that example was super useful! I now understand the point of this PR much better, and now it can be more easily taught and tested.
I've left a few comments for suggestions on how to make the example a bit gentler on beginners :) I think that I would also hook into Bevy's states to define whether or not asset loading is done, but I'm happy to get pushback if you feel otherwise.
Thanks! I made a few more updates to the example. I think it is now more useful as a template or as a guide to beginners. |
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.
Much improved! It's nice to see Bevy's states playing nicely with this style of logic.
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Added dev-dependency to event_listener. This is probably fine since `bevy_asset` and most of the `smol` ecosystem depend on it.
2f6d87a
to
b0c5818
Compare
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.
This is a nice PR overall, thanks for writing it up! I just have a couple of feedback items around the example which I think will help others understand what's happening.
} | ||
|
||
/// Wait for all [`AssetBarrierGuard`]s to be dropped asynchronously. | ||
pub fn wait_async(&self) -> impl Future<Output = ()> + 'static { |
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.
Nit: this should probably just be wait
since there won't be a sync alternative (a blocking wait
would be an anti-pattern).
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 think this is needed since impl Future<Output = ()> + 'static
is not 100% obvious to a new rust user that this is an async
function.
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.
That is also a fair point, happy with that as a reason!
Co-authored-by: Zachary Harrold <zac@harrold.com.au>
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.
This is cool. Sorry for getting in the way! I'm happy to help with the builder-related shenanigans.
/// | ||
/// The asset load will fail and an error will be printed to the logs if the asset stored at `path` is not of type `A`. | ||
#[must_use = "not using the returned strong handle may result in the unexpected release of the asset"] | ||
pub fn load_acquire<'a, A: Asset, G: Send + Sync + 'static>( |
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 didn't expect the builder-pattern to land quite so quickly (sorry about that), but it might be worth replacing these two functions with one in Ignore that, I misread which file this was in!NestedLoader
.
It might also make sense to support it for untyped handles, but I don't think that has to happen now.
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.
Yeah I think getting these ready is more important to keep the scope of this PR small.
There is already a public async
function for loading untyped assets so half of the use cases are already covered.
examples/asset/multi_asset_sync.rs
Outdated
// This showcases how to wait for assets synchronously. | ||
.add_systems(Update, wait_on_load) | ||
// This showcases how to wait for assets asynchronously. |
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.
nit: Both of these are asynchronous (in the more general sense), they even both poll. Might be worth phrasing it more like "how to poll until assets are loaded" and "how to wait for assets to load in a background task".
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.
Rephrased. I think "sync code" and "async code" are better descriptors than "synchronously" and "asynchronously". Added some explanations on polling as well.
Moved `main` on top. Used run condition to check whether assets are loaded. Separated setup methods for scene, ui and assets.
Objective
Supercedes #12881 . Added a simple implementation that allows the user to react to multiple asset loads both synchronously and asynchronously.
Solution
Added
load_acquire
, that holds an item and drops it when loading is finished or failed.When used synchronously
Hold an
Arc<()>
, check forArc::strong_count() == 1
when all loading completed.When used asynchronously
Hold a
SemaphoreGuard
, await onacquire_all
for completion.This implementation has more freedom than the original in my opinion.