#bevy-ecs #ecs #bevy #game

flat_commands

bevy ecs 扩展特质

4 个版本

0.4.0 2022年8月23日
0.2.2 2022年4月16日
0.2.1 2022年2月8日
0.2.0 2022年2月7日

#1825 in 游戏开发

MIT/Apache

200KB
488

Flat Commands

无需嵌套或收集ID即可生成实体层次结构。

示例

之前

fn setup(mut commands: Commands) {
    commands
        .spawn_bundle(PbrBundle {
            transform: Transform::from_xyz(1.0, 1.0, 1.0),
            ..Default::default()
        })
        .with_children(|parent| {
            parent
                .spawn_bundle(PbrBundle {
                    transform: Transform::from_xyz(1.0, 1.0, 1.0),
                    ..Default::default()
                })
                .spawn_bundle(PbrBundle {
                    transform: Transform::from_xyz(2.0, 2.0, 2.0),
                    ..Default::default()
                })
        });
}

fn setup(mut commands: Commands) {
    let child_1 = commands
        .spawn_bundle(PbrBundle {
            transform: Transform::from_xyz(1.0, 1.0, 1.0),
            ..Default::default()
        })
        .id();
    let child_2 = commands
        .spawn_bundle(PbrBundle {
            transform: Transform::from_xyz(2.0, 2.0, 2.0),
            ..Default::default()
        })
        .id();
    commands
        .spawn_bundle(PbrBundle {
            transform: Transform::from_xyz(1.0, 1.0, 1.0),
            ..Default::default()
        })
        .push_children(&[child_1, child_2]);
}

之后

use flat_commands::*;

fn setup(mut commands: Commands) {
    commands
        .spawn_root(PbrBundle {
            transform: Transform::from_xyz(1.0, 1.0, 1.0),
            ..Default::default()
        })
        .with_child(PbrBundle {
            transform: Transform::from_xyz(1.0, 1.0, 1.0),
            ..Default::default()
        })
        .with_sibling(PbrBundle {
            transform: Transform::from_xyz(2.0, 2.0, 2.0),
            ..Default::default()
        });
}

之前

fn spawn_text_box(
    mut commands: Commands,
    asset_server: Res<AssetServer>,
) {
 
    commands.spawn_bundle(NodeBundle {
        style: Style {
            position_type: PositionType::Absolute,
            position: UiRect { left: Val::Px(100.0), bottom: Val::Px(100.0), ..Default::default() },
            padding: UiRect::all(Val::Px(2.0)),
            ..Default::default()
        },
        ..Default::default()
    })
    .with_children(|builder| {
        builder.spawn_bundle(NodeBundle {
                color: UiColor (Color::DARK_GRAY),
                style: Style {
                    padding: UiRect::all(Val::Px(4.0)),
                    ..Default::default()
                },
                ..Default::default()
            }
        )
        .with_children(|builder| {
            builder.spawn_bundle(TextBundle {
                text: Text::from_section(
                    "Hello, world!",
                    TextStyle {
                        font: asset_server.load("FiraMono-Regular.ttf"),
                        font_size: 16.0,
                        color: Color::ANTIQUE_WHITE,
                    },
                ),
                 ..Default::default()
            });
        });
    });
}

之后

use flat_commands::*;

fn spawn_text_box(
    mut commands: Commands,
    asset_server: Res<AssetServer>,
) {
    commands.spawn_root(NodeBundle {
        style: Style {
            position_type: PositionType::Absolute,
            position: UiRect { left: Val::Px(100.0), bottom: Val::Px(100.0), ..Default::default() },
            padding: UiRect::all(Val::Px(2.0)),
            ..Default::default()
        },
        ..Default::default()
    })
    .with_child(NodeBundle {
        color: UiColor (Color::DARK_GRAY),
        style: Style {
            padding: UiRect::all(Val::Px(4.0)),
            ..Default::default()
        },
        ..Default::default()
    })
    .with_child(TextBundle {
        text: Text::from_section(
            "Hello, world!",
            TextStyle {
                font: asset_server.load("FiraMono-Regular.ttf"),
                font_size: 16.0,
                color: Color::ANTIQUE_WHITE,
            }
        ),
        ..Default::default()
    });
}

之前

fn spawn_branching_hierachy(
    commands: &mut Commands
) -> Entity {
    let id = commands.spawn().id();

    commands.entity(id)
    .with_children(|builder| {
        builder
        .spawn()
        .with_children(|builder| {
            builder
            .spawn()
            .with_children(|builder| {
                builder
                .spawn();

                builder
                .spawn();
            });
        });

        builder
        .spawn()
        .with_children(|builder| {
            builder
            .spawn()
            .with_children(|builder| {
                builder
                .spawn();

                builder
                .spawn();
            });
        });

        builder
        .spawn()
        .with_children(|builder| {
            builder
            .spawn()
            .with_children(|builder| {
                builder
                .spawn();

                builder
                .spawn();
            });
        });
    });

    id
}

之后

use flat_commands::*;

fn spawn_branching_hierachy(
    commands: &mut Commands
) -> Entity {
    commands
    .spawn_empty_root()
    .with_descendants(|local_root| {
        local_root
        .with_empty_child()
        .with_empty_child()
        .with_empty_sibling()
    })
    .with_descendants(|local_root| {
        local_root
        .with_empty_child()
        .with_empty_child()
        .with_empty_sibling()
    })
    .with_descendants(|local_root| {
        local_root
        .with_empty_child()
        .with_empty_child()
        .with_empty_sibling()
    })
    .root_id()
}

use flat_commands::*;

fn spawn_hierachy(
    mut commands: Commands
) -> Entity {
    let root = commands
    .spawn_empty_root();

    root
    .with_empty_child()
    .with_empty_child()
    .with_empty_sibling();
    
    root
    .with_empty_child()
    .with_empty_child()
    .with_empty_sibling();
    
    root
    .with_empty_child()
    .with_empty_child()
    .with_empty_sibling()
    .root_id()
}

EntityCommands 也实现了扩展特质

use flat_commands::*;

fn spawn_hierachy(
    mut commands: Commands
) {
    let entity_commands = commands.spawn();
    entity_commands
    .insert(MyComponent)
    .with_empty_child()
    .with_empty_sibling();
}

批量子实体生成

use flat_commands::*;

fn spawn_brood(
    mut commands: Commands,
    asset_server: Res<AssetServer>,
) {
    let font = asset_server.load("fonts/FiraSans-Bold.ttf");
    commands.spawn_root(NodeBundle { ..Default::default() })
    .with_child_batch((0..30).map(move |i| {
        TextBundle {
            text: Text::with_section(
                format!("Item {}", i),
                TextStyle {
                    font: font.clone(),
                    font_size: 20.,
                    color: Color::RED,
                },
                Default::default(),
            ),
            ..Default::default()
        }
    );
}

示例

在 /examples 文件夹中有一个创建文本框的最小示例。要运行,请使用

cargo run --example text_box

其他信息

  • 未优化,速度将低于 with_children 和 push_children。
  • 不会进行任何销毁或组件移除(使用常规命令)。
  • 不使用任何不安全代码或宏。
  • 3.0 版本支持 Bevy 0.8,2.2 版本支持 Bevy 0.7,> 2.2 版本支持 Bevy 0.6
  • 待办事项:自动标记组件插入。

依赖项

~15–33MB
~495K SLoC