Skip to content

Add collision prevention to HandleId::random() #3993

@BGR360

Description

@BGR360

Background

Background

At the time of writing the Bevy version is 0.6.1.

Here is the implementation of HandleId::random():

pub fn random<T: Asset>() -> Self {
HandleId::Id(T::TYPE_UUID, rand::random())
}

Here is where the method is used in bevy_asset:

/// Adds an asset to the collection, returning a Strong handle to that asset.
///
/// # Events
/// * [`AssetEvent::Created`]
pub fn add(&mut self, asset: T) -> Handle<T> {
let id = HandleId::random::<T>();
self.assets.insert(id, asset);
self.events.send(AssetEvent::Created {
handle: Handle::weak(id),
});
self.get_handle(id)
}

I use this method manually to immediately return a handle to an asset that I will generate asynchronously, and then later use Assets::set_untracked to place the generated asset into the collection.

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

Problem: It's possible (although unlikely) for HandleId::random() to produce a HandleId that is already in use by an existing asset in the Assets collection. This would result in overwriting the existing asset rather than adding a new one. This would be confusing for the user and very difficult to root-cause (and nearly impossible to reproduce).

What solution would you like?

Require users to provide a &Assets<T> reference so that collisions can be detected and the dice can be re-rolled:

fn random<T: TypeUuid>(assets: &Assets<T>) -> Self {
    loop {
        let handle_id = HandleId::Id(T::TYPE_UUID, rand::random());
        if !assets.contains(handle_id) {
            return handle_id;
        }
    }
}

What alternative(s) have you considered?

Implement the suggestion above, but do so as an additional method and call it something like random_unique().

Additional context

We may well decide that the likelihood of this is so low that it's not worth bothering.

See also a short Discord conversation here: https://discord.com/channels/691052431525675048/749332104487108618/944733810577264720

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-AssetsLoad files from disk to use for things like images, models, and soundsC-BugAn unexpected or incorrect behaviorC-Code-QualityA section of code that is hard to understand or change

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions