#entity-component #consumer #macro #avoiding #system #entities #object

nightly simple_ecs

Rust中一个超级简单的实体-组件系统

10个版本

使用旧的Rust 2015

0.3.2 2016年4月4日
0.3.1 2016年4月4日
0.2.2 2016年3月31日
0.1.5 2016年3月28日

#1902游戏开发

34 每月下载次数

GPL-3.0 许可证

18KB
483

ECS.rs

一个用Rust编写的实体-组件系统,主要关注在消费者中避免宏的使用并最小化样板代码。这里的突破性进展是Rust的类型和特质系统允许进行完全疯狂的操作。实现可以替换基于Any的虚函数调用使用更多的unsafe代码,但除此之外,单态化和内联意味着基本上所有的类型操作仍然意味着代码与手动编写的样板代码相同。

一个复杂但相当贴近现实世界的例子(来自我自己的游戏)

struct CameraComponent;
impl SetComponent for CameraComponent {}

struct RenderComponent {
	texture: Texture2d,
	depth: i8,
}
impl SetComponent for RenderComponent {}

struct VelocityComponent(f64, f64);
impl SetComponent for VelocityComponent {}

struct PositionComponent(f64, f64);
impl SetComponent for PositionComponent {}

struct ClipComponent(u32, u32, u32, u32);
impl SetComponent for ClipComponent {}

struct ScaleComponent(f64);
impl SetComponent for ScaleComponent {}

struct RenderSystem;

impl SimpleSystem<(), UpdateData> for RenderSystem {
	type Input = Either<(
		&'static RenderComponent,
		&'static PositionComponent,
		Option<&'static ClipComponent>,
		Option<&'static ScaleComponent>,
	), (
		&'static PositionComponent,
		&'static CameraComponent,
	)>;
	type Output = ();

	fn update(
		&mut self,
		entities: &[
			(
				EntityId,
				Either<(
					&RenderComponent,
					&PositionComponent,
					Option<&ClipComponent>,
					Option<&ScaleComponent>,
				), (
					&PositionComponent,
					&CameraComponent,
				)>
			)
		],
		ud: &UpdateData
	) -> Vec<(EntityId, (), ())> {
		unimplemented!();
	}
}

每个实体都有一个与其实体相关联的异构组件列表。这些组件打算作为纯数据对象,这就是为什么更新接收一个不可变引用而不是一个可变引用的原因。如果你没有修改特定的组件,你不需要在函数中传递它,这在大多数函数式风格/不可变实体-组件系统中是必须做的。如果你需要更多对实体的控制,例如添加新实体或删除现有实体等,你可以实现System而不是SimpleSystem。

待办事项

  • 允许并行运行Output=()系统。这可能会通过创建一个新的ReadonlySystem特质并为其 blanket implementing 以 T: SimpleSystem<Input=_, Output=()> + Send 来实现,然后让SystemStore类型有分离的读写系统列表。也许会有预处理和后处理的RO系统列表,但这将在我个人需要时添加。
  • 为Either<A, B>实现SetComponent(它将简单地转发到其中的任何一个)。
  • 使用impl specialization为T实现SetComponent。

依赖项

~19KB