#ecs #gamedev #game

星座

一个针对缓存一致性资源访问和并行系统执行优化的数据导向实体组件系统

2个不稳定版本

使用旧Rust 2015

0.2.0 2017年1月9日
0.1.0 2016年12月24日

#1021 in 游戏开发

Apache-2.0

100KB
2K SLoC

星座ECS

一个针对缓存一致性资源访问和并行系统执行优化的数据导向实体组件系统。

星座不自带对“组件”的任何原生理解。相反,该库关注确保安全并发访问共享资源,同时直接提供对每个资源自身的API的访问。这些资源可能存储每个实体的数据,如位置,也可能表示应用程序范围内的服务,如资源加载器或输入设备。

系统请求对一组资源的读取或写入访问,这些资源随后可以记录到SystemCommandBuffer中,并在World中执行命令缓冲区。

Crates.io
文档

类似项目

示例

定义资源

// Per-entity position data.
struct Position {
    x: f32,
    y: f32,
    z: f32
}

// Store position data into a vector resource
type Positions = VecResource<Position>;

// Per-entity debug names.
struct DebugName {
    name: String
}

// Store debug names in a map resource
type DebugNames = MapResource<DebugName>;

let mut world = World::new();
world.register_resource(Positions::new());
world.register_resource(DebugNames::new());

使用系统更新世界

let mut update = SystemCommandBuffer::default();
update.queue_systems(|scope| {
    scope.run_r1w1(|ctx, velocities: &Velocities, positions: &mut Positions| {
        println!("Updating positions");
        // iterate through all components for entities with data in both
        // position and velocity resources
        ctx.iter_r1w1(velocities, positions).components(|entity, v, p| {
                p.x += v.x;
                p.y += v.y;
                p.z += v.z;
        });
    });

    scope.run_r2w0(|ctx, names: &DebugNames, positions: &Positions| {
        println!("Printing positions");
        // iterate through all entity IDs for entities with data in both
        // `names` and `positions`
        ctx.iter_r2w0(names, positions).entities(|entity_iter, n, p| {
            // `n` and `p` allow (potentially mutable) access to entity data inside
            // the resource without the ability to add or remove entities from the resource
            // - which would otherwise invalidate the iterator
            for e in entity_iter {
                println!("Entity {} is at {:?}",
                         n.get(e).unwrap().name,
                         p.get(e).unwrap());
            }
        });
    });
});
world.run(&mut update);

并行系统执行

在单次调用queue_systems中将系统排队到命令缓冲区时,世界可以并行执行这些系统。

系统排队的顺序在某种程度上很重要:调度器保证资源的变化总是以系统排队的相同顺序被观察到。

例如,给定两个系统 - ReadPositionsWritePositions - 如果WritePositionsReadPositions之前排队,则保证ReadPositions将看到WritePositions所做的任何更改。相反,如果顺序被交换,则保证ReadPositions不会观察到WritePositions所做的更改。

对此有一个例外。实体删除在所有并发执行的系统完成后提交。这种行为是确定的,但并不总是显而易见的。如果您想确保一个系统中的实体删除总是被后续系统看到,那么请将两个系统分别排队到单独的queue_systems调用中。

依赖关系

~2MB
~33K SLoC