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

0.3.0 2023年7月22日
0.2.2 2023年6月17日
0.1.2 2023年6月6日
0.0.9 2023年6月5日
0.0.4 2023年5月29日

数据结构 中排名第641

Download history 5/week @ 2024-03-10 89/week @ 2024-03-31 1/week @ 2024-04-07

每月下载量163

MIT/Apache

155KB
2K SLoC

gecs 🦎

生成的实体组件系统。

Documentation Crates.io

gecs crate提供了一种编译时生成的、零开销的ECS,用于低成本模拟。与其他ECS库不同,gecs从代码中获取完整的ECS世界结构定义,并预编译所有查询,以在不产生任何前期成本或缓存开销的情况下实现更好的性能。gecs中的查询可以在编译时进行检查和验证,以捕捉在其他情况下仅在测试或执行中出现的错误。然而,这需要所有原型在编译时都必须已知并声明,因此目前无法在运行时向实体添加或删除组件——混合方法可能在未来解决这个问题。

gecs中的原型可以设置为包含固定或动态的实体容量。如果您的ECS世界声明中的所有原型都设置为固定容量,gecs在启动后将不会进行任何分配。这保证了您的ECS世界将遵循已知且可预测的内存开销,适用于受限环境(例如云实例上的服务器)。尝试向已满的原型添加实体可能会根据您调用的方法报告失败或引发恐慌。

gecs的目标(按优先级顺序排列)

  • 快速迭代和查找查询
  • 快速实体创建和销毁
  • 低且可预测的内存开销
  • 用户友好的库界面
  • 功能的简单性和专注

gecs生成的所有代码都是安全的,并且gecs用户可以在自己的crates中使用#[deny(unsafe_code)]。请注意,gecs在内部使用不安全代码以允许围绕已知的不变量进行编译器优化。这个库的目标不是完全用安全Rust编写。

入门指南

查看 ecs_world!ecs_find!ecs_iter! 宏获取更多信息。以下示例创建了一个包含三个组件和两个原型的世界

use gecs::prelude::*;

// Components -- these must be pub because the world is exported as pub as well.
pub struct CompA(pub u32);
pub struct CompB(pub u32);
pub struct CompC(pub u32);

ecs_world! {
    // Declare two archetypes, ArchFoo and ArchBar.
    ecs_archetype!(ArchFoo, 100, CompA, CompB); // Fixed capacity of 100 entities.
    ecs_archetype!(ArchBar, dyn, CompA, CompC); // Dynamic (dyn) entity capacity.
}

fn main() {
    let mut world = World::default(); // Initialize an empty new ECS world.

    // Add entities to the world by populating their components and receive their handles.
    let entity_a = world.create::<ArchFoo>((CompA(1), CompB(20)));
    let entity_b = world.create::<ArchBar>((CompA(3), CompC(40)));

    // Each archetype now has one entity.
    assert_eq!(world.len::<ArchFoo>(), 1);
    assert_eq!(world.len::<ArchBar>(), 1);

    // Look up each entity and check its CompB or CompC value.
    assert!(ecs_find!(world, entity_a, |c: &CompB| assert_eq!(c.0, 20)));
    assert!(ecs_find!(world, entity_b, |c: &CompC| assert_eq!(c.0, 40)));

    // Add to entity_a's CompA value.
    ecs_find!(world, entity_a, |c: &mut CompA| { c.0 += 1; });

    // Sum both entities' CompA values with one iter despite being different archetypes.
    let mut sum = 0;
    ecs_iter!(world, |c: &CompA| { sum += c.0 });
    assert_eq!(sum, 5); // Adding 2 + 3 -- recall that we added 1 to entity_a's CompA.

    // Collect both entities that have a CompA component.
    let mut found = Vec::new();
    ecs_iter!(world, |entity: &EntityAny, _: &CompA| { found.push(*entity); });
    assert!(found == vec![entity_a.into(), entity_b.into()]);

    // Destroy both entities -- this will return an Option containing their components.
    assert!(world.destroy(entity_a).is_some());
    assert!(world.destroy(entity_b).is_some());

    // Try to look up a stale entity handle -- this will return false.
    assert_eq!(ecs_find!(world, entity_a, |_: &Entity<ArchFoo>| { panic!() }), false);
}

许可证

您可以选择Apache 2.0或MIT许可证来使用此库。

依赖关系

~1.4–2MB
~39K SLoC