ECS架构之Entity设计与传统OOP的碰撞思考

ECS(Entity-Component-System)架构 中,Entity(实体)本身不需要显式分类型。

这是 ECS 的核心设计思想之一:实体是纯粹的、无类型的标识符(ID),其行为和属性完全由 组合的组件(Component) 决定,而非通过类型继承或分类实现。

为什么不需要分类型?

动态组合性

实体通过添加/移除组件来改变行为,而非通过类型。例如:

  • 一个“怪物”实体可以通过添加 PlayerControlled 组件变成“玩家角色”。
  • 一个“道具”实体可以通过添加 CombatStats 组件变成“武器”。

避免类型爆炸

传统 OOP 中,类型继承会导致类层级膨胀(如 Monster → Boss → FireBoss)。ECS 中只需组合组件

// 用组件组合替代类型继承
const boss = {
    id: 1,
    components: [CombatStats, BossAI, FireEffects, LootTable]
};

系统查询的灵活性

系统通过组件组合查询实体,而非类型。例如:

  • MovementSystem 查询所有包含 Position 和 Velocity 组件的实体。
  • TurnSystem 查询所有包含 TurnOrder 组件的实体。

如何替代“类型”概念?

传统类型思维ECS 替代方案
类型继承(class Monster)组件组合([Health, AI, Sprite])
类型标签(enum EntityType)用 标记组件(如 IsPlayer)
类型检查(if (entity is Monster))查询组件(hasComponent(entity, “Health”))

实战案例:回合制战斗中的实体设计

场景需求

  • 玩家、敌人、技能、障碍物等需要不同的行为。
  • 某些敌人是“Boss”,需要特殊逻辑。

ECS 实现

实体定义(无类型)

// 玩家实体
const player = {
    id: 1,
    components: [Position, Health, PlayerControlled, Skills]
};

// 普通敌人
const enemy = {
    id: 2,
    components: [Position, Health, AI, Sprite]
};

// Boss 敌人(仅多一个标记组件)
const boss = {
    id: 3,
    components: [Position, Health, AI, Sprite, IsBoss, LootTable]
};

系统逻辑

  • TurnSystem:查询所有含 TurnOrder 的实体。
  • AISystem:查询含 AI 但不含 PlayerControlled 的实体。
  • BossRewardSystem:查询含 IsBoss 和 Health(且血量≤0)的实体。

动态改变类型

// 敌人被玩家招募?移除 AI 组件,添加 PlayerControlled
removeComponent(enemy, "AI");
addComponent(enemy, PlayerControlled);

ECS 的优势正是通过 消除类型耦合 来实现高度灵活的设计,这在回合制战斗中尤其重要(如动态技能效果、状态叠加等)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值