2 个不稳定版本

0.2.0 2020 年 10 月 24 日
0.1.0 2020 年 4 月 12 日

#491 in 游戏开发

MIT/Apache

115KB
3K SLoC

goggles

它就像一副漂亮的太阳镜,只是不舒服且不方便


Build Status Latest Version API Documentation

这个包是 specs ECS 库的重度修改和精简版本。它与其说是一个用于尽可能轻松地完成特定风格的 ECS 的框架,不如说是一个 DIY 库,允许您根据自己需求进行修改。

goggles 可能不如其他 ECS 库(如 specslegion)容易使用,如果类似 specslegion 的库已经满足您的需求,那么您可能应该使用它。


基本数据结构设计几乎与 specs 完全相同,它使用与 specs 相同的基本数据结构来存储组件和执行连接。就像 specs 一样,它将组件存储在单独的存储中,并使用来自 hibitset 的分层位集合来记录它们的存在,并使用该分层位集合来执行连接。

然而,在此基础上,它提供的 API 比甚至 specs 还要简洁和零散。它在删除方面有些主观:我感到所有不必要的或神秘的东西,只尝试处理非常 困难 的操作或是不安全的操作,并将更容易的部分留给用户自行设计。

该库包含一系列相对独立的组件,您可以在适当的抽象级别停止

  1. par_seq 模块是完全独立的方式来设置和运行通用的并行和顺序系统。它可以与 shred 相比较,但它包含一个更通用的 System 特性,并且不包含锁定和读取资源的功能。它只是允许您在 System 中定义一组资源,使用 ParSeq 组合这些系统,确保结果没有资源冲突,然后运行它。

  2. system_data 模块为 par_seq 模块定义了一个用于静态定义资源的 SystemData 特性,并为 SystemData 的元组提供了实现。

  3. resource_set 模块定义了一个类似于 AnyMapResourceSet,其值存储在 RwLock 中。与一组 RwLock 不同,它永远不会阻塞,而是在别名规则被违反时直接引发恐慌。它被设计成可以使用 par_seq 模块构建在定义资源上运行的系统。它还包括方便的类型来定义和请求对实现 SystemData 的资源的读写句柄,因此它们可以用于类似 (Read<ResourceA>, Write<ResourceB>) 的元组中。它与 shred 中的 World 类型非常相似。

  4. join 模块包含一个为 u32 索引存储和由 BitSet 跟踪的 Join 特质的定义。它提供了快速、不安全的访问,并且能够安全地顺序和并行迭代 Join,还提供了将多个 Join 实例连接在一起的手段。它与 specs 中的 Join 特质类似,但为了提高安全性而进行了重新设计。

  5. storage 模块包含 RawStorage 特质以及 3 个有用的实现:VecStorageDenseVecStorageHashMapStorage。这是一个存储与索引关联的值的抽象、不安全特质。它与 specs 中的等效功能非常相似。

  6. tracked 模块包含一个跟踪组件变化的 RawStorage 包装器。与 specs 不同,这相当简约,仅在可选的情况下在可变访问时在 AtomicBitSet 中设置一个标志。

  7. masked 模块包含一个 MaskedStorage 结构,该结构安全地封装了一个 RawStorage 和一个 BitSet 来跟踪哪些组件存在。MaskedStorage 也支持连接。

  8. entity 模块包含一个原子生成索引分配器,它还使用 hibitset 类型来跟踪哪些索引是活动的。它还允许你连接到分配器以输出活动的 Entity

  9. world 模块将所有这些功能结合在一起,形成了一个具有可识别的 ECS API 的系统。如果你想了解它是如何工作的,或者想构建自己的抽象而不是这个模块中提供的,请从这里开始。对 specs 的许多更改都是为了使 world 模块只包含安全代码。


以下是移除自 shredspecs 的一些重要内容的未完整列表

  1. 没有自动设置,你必须插入/注册所有资源和组件类型。

  2. 没有保存/加载支持,你应该自己处理。

  3. 没有自动系统调度/分派/批处理,你必须自己使用 parseq 设计执行策略,然后在启动时检查冲突。

  4. 没有懒更新,你可能需要为你的应用程序专门处理。并不总是有一种普遍的最佳方式来做这件事。

以下是从 specs 中提取的关于该库和 specs 共同功能的重要变更的不完整列表

  1. 不需要 T: Sync 来进行对资源/组件的可变访问(只需要 T: Send)。

  2. 重新设计了 Join 特性,以增强健壮性和安全性。还有一个额外的 IntoJoin 特性,允许您在不编写不安全代码的情况下参与方便的元组连接语法。

  3. 组件 RawStorage 的实现需要 UnsafeCell 来保证健壮性。

  4. 组件 RawStorage 的实现始终假设存储是互斥的,并且可以安全地并行迭代。

  5. 简化了组件修改跟踪。

  6. 移除了一些已知不健壮的 specs 功能,例如通过迭代器进行索引组件访问。

  7. 库的各个部分尽量松散耦合,有时以增加代码或用户便利性为代价。

  8. 几乎所有的内部代码都是公开的,以便您可以根据需要构建不同的抽象。


为什么会有这个东西?

我一直在使用 specs 的项目,并且我不断需要重新设计它的一些小部分。多亏了 specs 的贡献,它已经是一个可以非常零散、独立使用的库,这正是我所做的。在某一点上,我抬头一看,意识到我只使用了 specs 提供的核心功能的约 20%,那时我开始需要使用杂乱的扩展特性来更进一步。我决定重新实现我仍然使用的 specs 的核心部分,把它和一些我制作的更灵活(但可能更难使用)的东西打包在一起(与 shred / specs 提供的东西相比),然后把它放在这里。

我应该使用这个吗?

您很可能不需要或想要这个crate。尽管如此,如果您发现自己需要将 specs 分解成其组成部分并在其上构建自己的API,这个crate就在这里供您使用。

致谢

本项目直接源自 specs,所以大部分功劳归于 specs 的创造者。这个crate中任何特别巧妙的东西可能都是他们的。

许可证

这是从 specs 衍生的,所以它同样采用 Apache-2.0 / MIT 双许可证。

依赖关系

~1.7–2.3MB
~48K SLoC