1个不稳定版本
新 0.1.0 | 2024年8月23日 |
---|
#561 in 游戏开发
每月 166 次下载
35KB
571 行
bevy_scene_postprocess
一个为Bevy提供的在加载场景后进行“后处理”的crate。
为什么?
场景很棒,但有一个大问题:它们通常是从GLTF加载的。这意味着场景的表现力受限于GLTF。像Blenvy这样的crate通过提供操作生成场景的方法(在Blenvy的情况下,通过将GltfExtra
解码为组件)使这变得更好。
虽然这很好,但存在一个尴尬的问题。这要求你生成场景,然后等待新生成的场景被处理。这意味着对场景的任何更改(例如,解码GltfExtra
)都需要在每次生成场景时重复。此外,这种方法与同步生成场景不兼容。
使用bevy_scene_postprocess
,你只需注册你的后处理操作,它将在所有操作完成后才分配场景。这意味着你只需在加载你的应用程序时执行一次操作,然后Bevy就只是生成场景而没有任何特殊之处。
另一个类似的crate是bevy_scene_hook
,但它是在生成完成后执行操作。注意,即使有后处理,bevy_scene_hook
仍然有用。也许你想要执行那些不适合“烘焙”到后处理中的对象操作。
如何使用
- 像平时一样加载一个场景。
- 调用
ScenePostProcessor::process
。 - 像平时一样使用返回的句柄(例如,在
SceneBundle
中)。
示例
以下示例只生成一次场景,该场景只包含Bar
use std::{
sync::Arc, time::Duration
};
use bevy::{
prelude::*, ecs::system::RunSystemOnce, scene::ScenePlugin,
time::common_conditions::once_after_delay
};
use bevy_scene_postprocess::{ScenePostProcessPlugin, ScenePostProcessor};
fn main() {
App::new()
.add_plugins(MinimalPlugins)
.add_plugins(AssetPlugin::default())
.add_plugins(ScenePlugin)
.add_plugins(ScenePostProcessPlugin)
.add_systems(Startup, register_post_process)
.add_systems(
Update,
fake_load_scene.run_if(once_after_delay(Duration::from_secs_f32(0.1))),
)
.add_systems(
Update,
(
move |mut exit: EventWriter<AppExit>| {
// Quite after loading to let the doctests pass.
exit.send(AppExit::Success);
}
).run_if(once_after_delay(Duration::from_secs_f32(0.5))),
)
.run();
}
fn register_post_process(
scenes: Res<Assets<Scene>>,
mut post_processor: ScenePostProcessor,
mut commands: Commands
) {
// Pretend we loaded an asset here (loading an asset for real would break
// doctests).
let handle = scenes.reserve_handle();
commands.insert_resource(LoadingHandle(handle.clone()));
let processed_scene = post_processor.process(handle, vec![
Arc::new(move |world: &mut World| {
// For example convenience, just run a system.
world.run_system_once(replace_foos_with_bar);
Ok(())
})
]);
commands.spawn(SceneBundle {
scene: processed_scene,
..Default::default()
});
}
#[derive(Resource)]
struct LoadingHandle(Handle<Scene>);
#[derive(Component)]
struct Foo;
#[derive(Component)]
struct Bar;
fn replace_foos_with_bar(foos: Query<Entity, With<Foo>>, mut commands: Commands) {
for entity in foos.iter() {
commands.entity(entity).remove::<Foo>().insert(Bar);
}
}
fn fake_load_scene(
handle: Res<LoadingHandle>,
mut scenes: ResMut<Assets<Scene>>
) {
let mut new_scene = Scene {
world: World::new(),
};
// Spawn three entities with `Foo`. They will be replaced with `Bar` by the
// post processing.
new_scene.world.spawn(Foo);
new_scene.world.spawn(Foo);
new_scene.world.spawn(Foo);
scenes.insert(&handle.0, new_scene);
}
许可证
根据以下任一许可证许可:
- Apache许可证第2版(LICENSE-APACHE 或 https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT许可证(LICENSE-MIT 或 http://opensource.org/licenses/MIT)
由你选择。
贡献
除非您明确声明,否则您根据Apache-2.0许可证定义的,有意提交以包含在该作品中的任何贡献,应按上述方式双重许可,不得附加任何其他条款或条件。
依赖项
~33–71MB
~1M SLoC