#specs #ecs #task #multitasking #entities #sequence #fork-join

specs-task

Fork-join多任务处理用于SPECS ECS

13个不稳定版本 (3个破坏性更新)

0.4.0 2020年6月16日
0.3.0 2020年6月5日
0.2.1 2020年5月20日
0.1.8 2020年2月1日
0.1.7 2019年1月23日

#900游戏开发

每月30次 下载

MIT 协议

44KB
787 代码行

Fork-join多任务处理用于SPECS ECS

不是通过手动滚动状态机来序列化各种ECS系统的效果,而是将任务作为实体生成,并在它们之间声明显式的时序依赖。

代码示例

制作任务图

fn make_static_task_graph(user: &TaskUser) {
    // Any component that implements TaskComponent can be spawned.
    let task_graph: TaskGraph = seq!(
        @TaskFoo("hello"),
        fork!(
            @TaskBar { value: 1 },
            @TaskBar { value: 2 },
            @TaskBar { value: 3 }
        ),
        @TaskZing("goodbye")
    );
    task_graph.assemble(user, OnCompletion::Delete);
}

fn make_dynamic_task_graph(user: &TaskUser) {
    let first = task!(@TaskFoo("hello"));
    let mut middle = empty_graph!();
    for i in 0..10 {
        middle = fork!(middle, @TaskBar { value: i });
    }
    let last = task!(@TaskZing("goodbye"));
    let task_graph: TaskGraph = seq!(first, middle, last);
    task_graph.assemble(user, OnCompletion::Delete);
}

使用TaskRunnerSystem构建分发器

#[derive(Clone, Debug)]
struct PushValue {
    value: usize,
}

impl Component for PushValue {
    type Storage = VecStorage<Self>;
}

impl<'a> TaskComponent<'a> for PushValue {
    type Data = Write<'a, Vec<usize>>;

    fn run(&mut self, data: &mut Self::Data) -> bool {
        data.push(self.value);

        true
    }
}

fn make_dispatcher() -> Dispatcher {
    DispatcherBuilder::new()
        .with(
            TaskRunnerSystem::<PushValue>::default(),
            "push_value",
            &[],
        )
        .with(
            TaskManagerSystem,
            "task_manager",
            &[],
        )
        .build()
}

依赖

~4.5MB
~89K SLoC