#bevy #scene #component #hook #insertion #game-engine #ad-hoc

bevy-scene-hook

为bevy场景提供即时组件插入功能

17个版本 (9个重大更新)

10.0.0 2024年2月19日
9.0.0 2023年11月4日
8.0.0 2023年8月30日
7.0.0 2023年7月9日
1.2.0 2022年3月22日

#421游戏开发

Download history 125/week @ 2024-04-08 88/week @ 2024-04-15 108/week @ 2024-04-22 83/week @ 2024-04-29 61/week @ 2024-05-06 86/week @ 2024-05-13 122/week @ 2024-05-20 57/week @ 2024-05-27 109/week @ 2024-06-03 133/week @ 2024-06-10 97/week @ 2024-06-17 71/week @ 2024-06-24 34/week @ 2024-07-01 39/week @ 2024-07-08 61/week @ 2024-07-15 37/week @ 2024-07-22

每月183 次下载
用于 6 个crate(直接使用2个)

Apache-2.0

39KB
197

Bevy Scene hook

Bevy tracking Latest version Apache 2.0 Documentation

Bevy游戏引擎中,向通过场景(例如gltf文件)创建的实体中(例如)即时添加组件的示例。

如果你不介意在代码中添加这样的小型依赖项而不是将代码作为模块粘贴,你可以在crates.io中获取它。

用法

  1. 将crate添加到依赖项中
[dependencies]
bevy-scene-hook = "10.0.0"
  1. 添加插件
.add_plugins(HookPlugin)

示例

use bevy::prelude::*;
use bevy_scene_hook::{SceneHook, HookedSceneBundle};

enum PileType { Drawing }

#[derive(Component)]
struct Pile(PileType);

#[derive(Component)]
struct Card;

fn load_scene(mut cmds: Commands, asset_server: Res<AssetServer>) {
   cmds.spawn(HookedSceneBundle {
       scene: SceneBundle { scene: asset_server.load("scene.glb#Scene0"), ..default() },
       hook: SceneHook::new(|entity, cmds| {
           match entity.get::<Name>().map(|t|t.as_str()) {
               Some("Pile") => cmds.insert(Pile(PileType::Drawing)),
               Some("Card") => cmds.insert(Card),
               _ => cmds,
           };
       }),
   });
}

在游戏开始时加载scene.glb文件。当场景完全加载后,将向场景中每个实体传递到SceneHook::new中的闭包。我们将一个Pile组件添加到具有Name组件值为"Pile"的实体。

在blender中,您可以使用Outliner窗口(右上角的树形视图)双击对象名称来在glb场景中命名对象。

请注意,SceneHook钩子一次只能访问一个EntityRefEntityCommands,并忽略资源重新加载。

考虑使用此crate的reload::Hook来处理更复杂的用例。

实现

bevy-scene-hook是一个小巧的crate,以下是你可以直接在项目中使用的可粘贴代码

use bevy::{
    prelude::*,
    scene::SceneInstance,
    ecs::{world::EntityRef, system::EntityCommands},
};
#[derive(Component, Debug)]
pub struct SceneHooked;

#[derive(Component)]
pub struct SceneHook {
    hook: Box<dyn Fn(&EntityRef, &mut EntityCommands) + Send + Sync + 'static>,
}
impl SceneHook {
    pub fn new<F: Fn(&EntityRef, &mut EntityCommands) + Send + Sync + 'static>(hook: F) -> Self {
        Self { hook: Box::new(hook) }
    }
}

pub fn run_hooks(
    unloaded_instances: Query<(Entity, &SceneInstance, &SceneHook), Without<SceneHooked>>,
    scene_manager: Res<SceneSpawner>,
    world: &World,
    mut cmds: Commands,
) {
    for (entity, instance, hooked) in unloaded_instances.iter() {
        if scene_manager.instance_is_ready(**instance) {
            cmds.entity(entity).insert(SceneHooked);
        }
        let entities = scene_manager
            .iter_instance_entities(**instance)
            .chain(std::iter::once(entity));
        for entity_ref in entities.filter_map(|e| world.get_entity(e)) {
            let mut cmd = cmds.entity(entity_ref.id());
            (hooked.hook)(&entity_ref, &mut cmd);
        }
    }
}

pub struct HookPlugin;
impl Plugin for HookPlugin {
    fn build(&self, app: &mut App) { app.add_systems(Update, run_hooks); }
}

请注意,bevy-scene-hook还定义了一些用于用户方便的项

  • HookedSceneBundle
  • HookedSceneState
  • is_scene_hooked

这些额外的项都在lib.rs中定义。

变更日志

  • 1.1.0:向SceneInstance添加is_loaded方法
  • 1.2.0:添加包含具有独占世界访问权限的 SceneHook 特质的 world 模块。如果您想访问资源,例如,这很有用。
  • 2.0.0破坏性更改:将 bevy 版本提升到 0.7(您应该能够在不更改代码的情况下从 1.2.0 升级)
  • 3.0.0破坏性更改:完全重构了 crate。
    • 移除了 world 模块,因为基本钩子方法变得非常强大。
    • SceneHook 重命名为 Hook,现在 Hook 有一个独特的实现方法。
    • 现在您不需要自己添加任何系统,您需要将 HookPlugin 插件添加到您的应用程序中。
    • 将 API 独家移动到新的 SystemParamHookingSceneSpawner。请使用该参数添加和删除包含钩子的场景。(如果您不小心将其拼写为 HonkingSceneSpawner 两次以上,请告诉我 🦆)
    • when_spawned 运行条件移动到 crate 根处的 is_scene_hooked 函数、HookedSceneState 系统参数或 SceneLoaded 组件。请使用这三个中的任何一个而不是 when_spawned
    • 现在支持将闭包作为钩子传递,而不是每次都要定义一个特质。
    • 现在支持添加多个相同的场景!不处理热重载,但这没关系,因为 bevy 的场景热重载目前是损坏的 :D
  • 3.1.0:将 run_hooks 系统公开,以便您可以将其添加到您想要添加的任何阶段,与任何其他系统相关联。
  • 4.0.0破坏性更改:将 bevy 版本提升到 0.8
    • 使用新的场景包系统
    • SceneLoaded 重命名为 SceneHooked
    • 移除了 Hook 特质,现在 SceneHook::new 接受闭包。
    • 而不是使用 HookingSceneSpawner,使用 HookedSceneBundle 并将其实例化到实体中。
  • 4.1.0:添加 HookedDynamicSceneBundle 以与 DynamicScene 一起使用。感谢 Shatur (https://github.com/nicopap/bevy-scene-hook/pull/3
  • 5.0.0破坏性更改:将 bevy 版本提升到 0.9
  • 5.1.1:我的失误,不小心发布到了版本 5.1.0,而不是 5.0.0
  • 5.1.2:修复了由于缺少检查而导致场景从未触发钩子的问题。感谢 sdfgeoff (#5) 如果你将 bevy-scene-hook 作为 cargo 依赖项,必须运行 cargo update 以获取此修复。
  • 5.2.0:添加了 reload 模块,定义了 reload::Hook,它是 SceneHook 的一个变体,可以优雅地处理重新加载和卸载。
  • 6.0.0破坏性更改:将 bevy 版本提升到 0.10
  • 7.0.0破坏性更改:将 bevy 版本提升到 0.11
  • 8.0.0:将场景的根实体添加到遍历场景实体列表中。
  • 9.0.0破坏性更改:将 bevy 版本提升到 0.12
    • hook 函数移动到 SpawnScene 调度中
  • 10.0.0破坏性更改:将 bevy 版本提升到 0.13
    • 移除 file_path reload::Hook 字段,转而使用 Handle::path 方法。
    • 添加示例并测试 Readme。

版本矩阵

bevy 最新支持的版本
0.13 10.0.0
0.12 9.0.0
0.11 8.0.0
0.10 6.0.0
0.9 5.2.0
0.8 4.1.0
0.7 3.1.0
0.6 1.2.0

许可证

本库采用 Apache 2.0 许可。

依赖项

~22–56MB
~1M SLoC