#hecs #parallel #execution #systems #framework #schedule #hecs-schedule

despero-hecs-schedule

为 hecs 提供可调度的系统和并行执行

1 个不稳定版本

0.6.2 2023 年 5 月 27 日

#496并发

Download history 6/week @ 2024-03-11 14/week @ 2024-03-25 23/week @ 2024-04-01 2/week @ 2024-05-13 14/week @ 2024-05-20 8/week @ 2024-05-27 14/week @ 2024-06-03 13/week @ 2024-06-10 9/week @ 2024-06-17 15/week @ 2024-06-24

51 每月下载量
用于 7 个 Crates (2 直接使用)

自定义许可证

66KB
1.5K SLoC

hecs-schedule

Hecs-schedule

hecs-schedule 是一个为 hecs 提供系统抽象的并行执行框架。

子世界

SubWorld 允许将世界分割成更小的部分,这些部分只能访问子集组件。这允许

命令缓冲区

CommandBuffer 通过组件插入、移除、实体生成和销毁等方式,提供了延迟的世界修改,以及通过闭包在以后时间进行任意世界修改的能力。

命令缓冲区扩展了现有的 hecs::CommandBuffer 并提供了更多功能。

系统和调度

系统代表一个可以访问任何资源的单元工作。系统可以针对任何具有任意数量参数(好吧,由于元组大小和编译时间,有一个合理的限制)的函数和闭包进行实现。

系统可以访问子世界并安全地访问声明的组件。它还可以通过 ReadWrite 包装器访问任何其他类型的值。

此值将从提供的 Context 中提取,该 Context 被作为可变引用提供给 Schedule::execute。这意味着系统可以访问 ECS 外部的局部变量和结构成员。如果没有提供该类型的值,系统将干净地退出并返回错误。

系统可以返回空值或空结果,这将被正确装箱并传播

调度是一系列按顺序执行的系统。

当执行调度时,将为包含的系统提供引用的元组。

使用方法

use hecs_schedule::*;
use hecs::*;

let mut world = World::default();

#[derive(Debug)]
struct App {
    name: &'static str,
}

let mut app = App {
    name: "hecs-schedule"
};

// Spawn some entities
let a = world.spawn(("a", 42));
world.spawn(("b", 0));
world.spawn(("c", 7));

// Create a simple system to print the entities
let print_system = | w: SubWorld<(& &'static str, &i32)> | {
  w.query::<(&&'static str, &i32)>().iter().for_each(|(e, val)| {
    println!("Entity {:?}: {:?}", e, val);
  })
};

// Get a component from a specific entity, failing gracefully if the entity
// didn't exist or the subworld did not support the component. The result
// will propogate to the schedule execution.
let get_system = move | w: SubWorld<&i32> | -> anyhow::Result<()> {
  let val = w.get::<i32>(a)?;

  // Prints the answer to life, the universe, and everything.
  // Welp, maybe not how to please the borrow checker, but almost
  // everything.
  println!("Got: {}", *val);

  Ok(())
};

// Declare a system which borrows the app and prints it.
// This requires that a reference to app was provided to execute.
// Otherwise, the system fails and returns an error, which propogates to the
// schedule and stops execution.

// It is also possible to modify the app via `mut Write<App>`
let print_app = |app: Read<App>| {
    println!("App: {:?}", app);
};

// Note: the `hecs_schedule::CommandBuffer` is a superset of `hecs::CommandBuffer` and is
// accesible as a shared resource from systems.
let spawn_system = |mut cmd: Write<hecs_schedule::CommandBuffer>| {
    cmd.spawn(("c", 5));
};

// Construct a schedule
let mut schedule = Schedule::builder()
    .add_system(spawn_system)
    .add_system(print_system)
    .add_system(print_app)
    .add_system(get_system)
    .build();

// Execute the schedule's systems and provide the world and app. This will parallelize as much
// as possible.
schedule.execute((&mut world, &mut app)).expect("Failed to execute schedule");

依赖关系

~4MB
~75K SLoC