如何将组件添加到场景中生成的实体?
How to add components to entities spawned in a scene?
在具有以下名为 my_scene.scn
的场景文件的 Bevy 项目中:
[
(
entity: 0,
components: [
{
"type": "Transform",
"map": {
"translation": {
"type": "Vec3",
"value": (150.0, 200.0, 0.0),
},
"rotation": {
"type": "Quat",
"value": (0.0, 0.0, 0.0, 1.0),
},
"scale": {
"type": "Vec3",
"value": (0.75, 0.75, 0.0),
},
},
},
]
)
]
并且这个源代码遵循 这个官方 Bevy
例子:
use bevy::prelude::*;
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_startup_system(load_scene_system.system())
.run();
}
fn load_scene_system(asset_server: Res<AssetServer>, mut scene_spawner: ResMut<SceneSpawner>) {
let scene_handle: Handle<Scene> = asset_server.load("my_scene.scn");
scene_spawner.spawn_dynamic(scene_handle);
// ^ How to add components to entities created here ?
asset_server.watch_for_changes().unwrap();
}
我想向这个实体 0 添加其他组件,例如 SpriteComponents
。我该如何实现?
这是我想出的解决方案。这个想法是存储一个组件
包含创建更动态组件的信息。
例如,要动态加载场景文件中引用的精灵图像,我们
可以定义一个SpriteLoader
组件,然后添加一个系统,用我们想要的组件替换这个加载器组件。
use bevy::prelude::*;
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.register_component::<SpriteLoader>()
.add_startup_system(load_scene_system.system())
.add_system(load_sprite_system.system())
.run();
}
fn load_scene_system(asset_server: Res<AssetServer>, mut scene_spawner: ResMut<SceneSpawner>) {
let scene_handle: Handle<DynamicScene> = asset_server.load("my_scene.scn");
scene_spawner.spawn_dynamic(scene_handle);
asset_server.watch_for_changes().unwrap();
}
/// Component indicating that a sprite will be loaded for the entity.
#[derive(Properties, Default)]
pub struct SpriteLoader {
/// Path of the sprite to load
pub path: String
}
/// Replaces the `SpritLoader` component with the corresponding `SpriteComponents`.
pub fn load_sprite_system(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut materials: ResMut<Assets<ColorMaterial>>,
query: Query<(Entity, Added<SpriteLoader>)>,
) {
for (entity, sprite_loader) in query.iter() {
commands.remove_one::<SpriteLoader>(entity);
let path = PathBuf::from(sprite_loader.path.clone());
commands.insert(
entity,
SpriteComponents {
material: materials.add(asset_server.load(path).into()),
..SpriteComponents::default()
},
);
}
}
这里,一旦一个SpriteLoader
被添加到实体中,load_sprite_system
系统将删除它并插入一个
SpriteComponents
代替。根据 的文档
insert
, 这个
将替换之前的 SpriteComponents
.
对应的场景文件为:
[
(
entity: 0,
components: [
{
"type": "SpriteLoader",
"map": {
"path": "my_sprite.png",
},
},
]
)
]
在具有以下名为 my_scene.scn
的场景文件的 Bevy 项目中:
[
(
entity: 0,
components: [
{
"type": "Transform",
"map": {
"translation": {
"type": "Vec3",
"value": (150.0, 200.0, 0.0),
},
"rotation": {
"type": "Quat",
"value": (0.0, 0.0, 0.0, 1.0),
},
"scale": {
"type": "Vec3",
"value": (0.75, 0.75, 0.0),
},
},
},
]
)
]
并且这个源代码遵循 这个官方 Bevy 例子:
use bevy::prelude::*;
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_startup_system(load_scene_system.system())
.run();
}
fn load_scene_system(asset_server: Res<AssetServer>, mut scene_spawner: ResMut<SceneSpawner>) {
let scene_handle: Handle<Scene> = asset_server.load("my_scene.scn");
scene_spawner.spawn_dynamic(scene_handle);
// ^ How to add components to entities created here ?
asset_server.watch_for_changes().unwrap();
}
我想向这个实体 0 添加其他组件,例如 SpriteComponents
。我该如何实现?
这是我想出的解决方案。这个想法是存储一个组件 包含创建更动态组件的信息。
例如,要动态加载场景文件中引用的精灵图像,我们
可以定义一个SpriteLoader
组件,然后添加一个系统,用我们想要的组件替换这个加载器组件。
use bevy::prelude::*;
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.register_component::<SpriteLoader>()
.add_startup_system(load_scene_system.system())
.add_system(load_sprite_system.system())
.run();
}
fn load_scene_system(asset_server: Res<AssetServer>, mut scene_spawner: ResMut<SceneSpawner>) {
let scene_handle: Handle<DynamicScene> = asset_server.load("my_scene.scn");
scene_spawner.spawn_dynamic(scene_handle);
asset_server.watch_for_changes().unwrap();
}
/// Component indicating that a sprite will be loaded for the entity.
#[derive(Properties, Default)]
pub struct SpriteLoader {
/// Path of the sprite to load
pub path: String
}
/// Replaces the `SpritLoader` component with the corresponding `SpriteComponents`.
pub fn load_sprite_system(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut materials: ResMut<Assets<ColorMaterial>>,
query: Query<(Entity, Added<SpriteLoader>)>,
) {
for (entity, sprite_loader) in query.iter() {
commands.remove_one::<SpriteLoader>(entity);
let path = PathBuf::from(sprite_loader.path.clone());
commands.insert(
entity,
SpriteComponents {
material: materials.add(asset_server.load(path).into()),
..SpriteComponents::default()
},
);
}
}
这里,一旦一个SpriteLoader
被添加到实体中,load_sprite_system
系统将删除它并插入一个
SpriteComponents
代替。根据 的文档
insert
, 这个
将替换之前的 SpriteComponents
.
对应的场景文件为:
[
(
entity: 0,
components: [
{
"type": "SpriteLoader",
"map": {
"path": "my_sprite.png",
},
},
]
)
]