-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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 an abstraction like bundles that can define child entities as well #2565
Comments
I think some solution to the bundle with children -creation should be present. Ideally, it'd reduce the boilerplate code needed, and make the code cleaner. However, some questions related to the proposed solution:
I experimented with this solution a few days ago: use bevy::{ecs::system::EntityCommands, prelude::*};
pub trait EntityBuilder {
type Bundle: bevy::prelude::Bundle;
fn new() -> Self;
fn spawn<'a, 'b>(
&self,
cmd: &'b mut Commands<'a>,
meshes: &mut Assets<Mesh>,
materials: &mut Assets<StandardMaterial>,
) -> EntityCommands<'a, 'b> {
let mut entity_cmd = cmd.spawn_bundle(self.build_bundle());
entity_cmd.with_children(self.build_child_fn(meshes, materials));
entity_cmd
}
fn build_bundle(&self) -> Self::Bundle;
fn build_child_fn<'a>(
&self,
meshes: &mut Assets<Mesh>,
materials: &mut Assets<StandardMaterial>,
) -> Box<dyn FnOnce(&mut ChildBuilder)>; usage: let entity_id = MyBundleBuilder::new()
.set_transform(Transform::from_xyz(2., 3., 4.)) // the struct where `EntityBuilder` is implemented for can have additional methods
.spawn(&mut commands, &mut meshes, &mut materials)
.id(); and then the struct (e.g. Currently meshes & materials are hardcoded, that'll cause problems if other references are needed. |
To build groups of entities, I make a builder struct that contains a new |
You could make it possible to give initializer functions to bundles. On this thought is there a reason not to make bundles just functions itself? But I would love something like a Post-Initializer function. |
@mio991 to make sure to understand what you mean, could you show an example in Rust or pseudocode of what you would want to do? |
@mockersf I thought of something like pub struct TextBox {
pub node:NodeBundle,
/* cut for brevity */
}
impl Bundle for TextBox{
fn initialize(root: &mut ChildBuilder) {
root.spawn_bundle(
/* cut for brevity */
);
}
} but i don't know if this is possible or even the rust way. |
I played around a bit here is what I got: I don't want to open a pull request just know, because it doesn't currently work. |
had a brain wave. placeholder names. #[derive(Bundle)]
struct MyBundle {
sprite: Sprite2dBundle,
name: Name,
}
impl BundleWithChildren for MyBundle {
fn spawn_children(&self, builder: ChildBuilder){
builder.spawn(
Text2dBundle {
text: Text::from_section(self.name.clone(), TextStyle::default())
..default()
},
);
}
}
fn spawn_whatever(mut commands: Commands){
// might need to be like `spawn_with_children`, idk if there's some typing magic
commands.spawn(MyBundle {...});
} I have no idea how |
tried to implement this myself by adding a |
An abstraction like this will be required for the Prior third-party art includes This is related to #3877, which is a more complex version of this idea, targeted towards easy migrations. |
Note that since we have observers and hooks now, a possible workaround is something like this: #[derive(Bundle)]
pub struct PlayerBundle {
player: Player,
movement: Movement,
transform: Transform,
global_transform: GlobalTransform,
sprite: BundleChild<SpriteBundle>,
}
struct BundleChild<T: Bundle>(Option<T>);
impl<T: Bundle> BundleChild<T> {
fn new(value: T) -> Self {
Self(Some(value))
}
}
impl<T: Bundle> Component for BundleChild<T> {
const STORAGE_TYPE: StorageType = StorageType::Table;
fn register_component_hooks(hooks: &mut ComponentHooks) {
hooks.on_add(|mut world, entity, _component_id| {
let bundle = world.get_mut::<BundleChild<T>>(entity).unwrap().0.take();
if let Some(bundle) = bundle {
world.commands().entity(entity).with_children(|parent| {
parent.spawn(bundle);
});
}
});
}
} |
#14437 discusses this problem, as part of an overhaul to how scenes work and how entities are spawned. |
I've created a crate, This isn't a perfect solution (the requirement for unique component types really hurts), but it does a good job making |
What problem does this solve or what need does it fill?
It's just a syntax sugar for better entity code organization
What solution would you like?
What alternative(s) have you considered?
I can already spawn two entities and parent them together, but I would be easier to spawn an entity and alto spawn it's children.
The text was updated successfully, but these errors were encountered: