Skip to content

Users must specify storage type for Component when used as a trait object #3265

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

Closed
alice-i-cecile opened this issue Dec 6, 2021 · 3 comments
Labels
A-ECS Entities, components, systems, and events C-Bug An unexpected or incorrect behavior C-Usability A targeted quality-of-life change that makes Bevy easier to use

Comments

@alice-i-cecile
Copy link
Member

alice-i-cecile commented Dec 6, 2021

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

When attempting to create a trait object of a Component, users must specify the storage type as either Component<Storage=TableStorage> or Component<Storage=SparseStorage>.

Reproduction:

use bevy::prelude::*;

fn main() {
    let boxed_component: Box<dyn Component> = Box::new(Transform::identity());
}

If they do not do so, they receive a compiler error like:

the value of the associated type `Storage` (from trait `bevy::prelude::Component`) must be specified

This is both somewhat confusing to resolve and frustratingly limiting, as you cannot mix and match storage types within types that you intend to store in the same trait object.

What solution would you like?

Somehow refactor the way storage types are recorded (see bevyengine/rfcs#27 for alternate approaches) to avoid this limitation.

Additional context

Encountered when exploring topics related to #3227.

@alice-i-cecile alice-i-cecile added C-Bug An unexpected or incorrect behavior A-ECS Entities, components, systems, and events C-Usability A targeted quality-of-life change that makes Bevy easier to use labels Dec 6, 2021
@cart
Copy link
Member

cart commented Dec 6, 2021

Theres no (direct) way around this if we encode the storage type in the Trait implementation. We can't have our cake (using the type system to specialize Component implementations) and eat it too (treat all Component types the same in a boxed collection).

The workaround here is to split out a separate "unspecialized" version of the Component trait (containing global unspecialized behaviors) and box that. We can even auto implement that trait for all specialized Component impls. Or alternatively we can stop embedding storage type in the type system and go back to a single Component trait (and give up the perf wins that this affords us).

Before choosing a path forward I think we need to answer some questions: Do we actually need to box Components directly? If so, what is the use case?

@alice-i-cecile
Copy link
Member Author

Before choosing a path forward I think we need to answer some questions: Do we actually need to box Components directly? If so, what is the use case?

If we can solve #3227 in another form (such as support for Box<dyn Bundle>), I think that all of the major use cases would be covered nicely. There is still a bit of frustration when attempting to create trait objects out of traits that have a Component subtrait, but in that case choosing a storage type isn't too bad and the user pain could be resolved with decent docs on the Storage associated type.

Currently, I'm using designs with this pattern to dynamically add a collection of components to a Player entity based on the class they've selected. My workaround right now is to use methods like

trait Class {
 fn add_class_components(&self, player_entity: Entity, commands: &mut Commands)
}

I would also like to experiment with this style of dynamic bundle pattern for UI widgets.

This technically works, but it's a pretty unprincipled API and doesn't allow me to later inspect the bundle that would be added.

@alice-i-cecile
Copy link
Member Author

Closing this out as redundant to #3227.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ECS Entities, components, systems, and events C-Bug An unexpected or incorrect behavior C-Usability A targeted quality-of-life change that makes Bevy easier to use
Projects
None yet
Development

No branches or pull requests

2 participants