基于CocosCreator的ECS实现架构说明

71 阅读1分钟

ECS架构类图 - 简化版

核心架构图

graph TB
    subgraph "应用层"
        APP[Application<br/>单例应用]
    end
    
    subgraph "世界层"
        WORLD[World<br/>基础世界]
        GAME_WORLD[GameWorld<br/>游戏世界]
        BATTLE_WORLD[BattleWorld<br/>战斗世界]
    end
    
    subgraph "实体层"
        ENTITY[Entity<br/>基础实体]
        SINGLE_ENTITY[SingletonEntity<br/>单例实体]
        SCENE_ENTITY[SceneNodeEntity<br/>场景节点实体]
    end
    
    subgraph "组件层"
        COMPONENT[Component<br/>基础组件]
        SINGLETON[Singleton<br/>标识组件]
        RESOURCE_MGR[ResourceManager<br/>资源管理器]
        GAME_MGR[GameManager<br/>游戏管理器]
        UNIT[Unit<br/>兵种组件]
        MOVEMENT[Movement<br/>移动组件]
        COMBAT[Combat<br/>战斗组件]
    end
    
    subgraph "系统层"
        SYSTEM[System<br/>基础系统]
        GAME_SYSTEM[GameSystem<br/>游戏系统]
        SPAWN_SYSTEM[SpawnSystem<br/>召唤系统]
        MOVE_SYSTEM[MovementSystem<br/>移动系统]
    end
    
    subgraph "查询层"
        CONTEXT[IContext<br/>实体上下文]
        GROUP[IGroup<br/>实体组]
        MATCHER[IMatcher<br/>匹配器]
        COLLECTOR[ICollector<br/>响应收集器]
    end
    
    subgraph "管理层"
        SYS_MGR[SystemManager<br/>系统管理器]
        TIME_MGR[TimeManager<br/>时间管理器]
        TIME_CHANNEL[TimeChannel<br/>时间通道]
    end
    
    subgraph "集成层"
        SCHEDULER[ECSScheduler<br/>ECS调度器]
        LAUNCHER[GameLauncher<br/>游戏启动器]
    end
    
    APP --> WORLD
    WORLD --> GAME_WORLD
    WORLD --> BATTLE_WORLD
    
    WORLD --> CONTEXT
    CONTEXT --> ENTITY
    ENTITY --> COMPONENT
    
    WORLD --> SYS_MGR
    WORLD --> TIME_MGR
    TIME_MGR --> TIME_CHANNEL
    
    SYSTEM --> GROUP
    GROUP --> MATCHER
    SYSTEM --> COLLECTOR
    
    GAME_WORLD --> SINGLE_ENTITY
    SINGLE_ENTITY --> RESOURCE_MGR
    SINGLE_ENTITY --> GAME_MGR
    
    BATTLE_WORLD --> SCENE_ENTITY
    SCENE_ENTITY --> UNIT
    SCENE_ENTITY --> MOVEMENT
    SCENE_ENTITY --> COMBAT
    
    SYSTEM --> GAME_SYSTEM
    SYSTEM --> SPAWN_SYSTEM
    SYSTEM --> MOVE_SYSTEM
    
    LAUNCHER --> APP
    SCHEDULER --> APP
    
    style APP fill:#ff6b6b
    style WORLD fill:#4ecdc4
    style ENTITY fill:#95e1d3
    style COMPONENT fill:#f38181
    style SYSTEM fill:#aa96da
    style CONTEXT fill:#fcbad3
    style SYS_MGR fill:#a8d8ea
    style TIME_MGR fill:#a8d8ea

类关系详细图

classDiagram
    %% 核心应用
    Application "1" o-- "*" World : manages
    
    %% 世界继承关系
    World <|-- GameWorld
    World <|-- BattleWorld
    
    %% 实体继承关系
    Entity <|-- SingletonEntity
    Entity <|-- SceneNodeEntity
    
    %% 组件继承关系
    Component <|-- System
    Component <|-- Singleton
    Component <|-- ResourceManager
    Component <|-- GameManager
    Component <|-- Unit
    Component <|-- Movement
    Component <|-- Combat
    
    %% 系统继承关系
    System <|-- GameSystem
    System <|-- SpawnSystem
    System <|-- MovementSystem
    
    %% 世界包含关系
    World "1" *-- "*" IContext : contains
    World "1" *-- "1" TimeManager : has
    World "1" *-- "1" SystemManager : has
    
    %% 上下文管理实体
    IContext "1" *-- "*" Entity : manages
    IContext "1" *-- "*" IGroup : creates
    IContext "1" *-- "*" IMatcher : creates
    
    %% 实体包含组件
    Entity "1" *-- "*" Component : contains
    
    %% 系统使用组和收集器
    System "1" *-- "*" IGroup : uses
    System "1" *-- "*" ICollector : uses
    
    %% 组使用匹配器
    IGroup "1" *-- "1" IMatcher : uses
    IGroup "1" *-- "*" Entity : contains
    
    %% 时间管理
    TimeManager "1" *-- "*" TimeChannel : manages
    
    %% 单例关系
    GameWorld "1" *-- "1" ResourceManager : singleton
    GameWorld "1" *-- "1" GameManager : singleton

数据流图

sequenceDiagram
    participant GL as GameLauncher
    participant ES as ECSScheduler
    participant APP as Application
    participant W as World
    participant TM as TimeManager
    participant SM as SystemManager
    participant SYS as System
    participant G as IGroup
    participant E as Entity
    
    Note over GL: 游戏启动
    GL->>ES: active = true
    GL->>APP: world("main", GameWorld)
    APP->>W: initialize()
    W->>W: launch()
    W->>SYS: onAwake()
    W->>SYS: onEnable()
    
    Note over ES: 每帧更新
    ES->>APP: update(timestamp)
    APP->>W: update(timestamp)
    W->>TM: update(timestamp)
    TM->>SM: update()
    SM->>SYS: onUpdate(deltaTime)
    SYS->>G: 查询实体
    G->>E: 遍历匹配的实体
    SYS->>E: 处理组件数据

实体创建流程

flowchart TD
    A[开始] --> B[Context.createEntity]
    B --> C[Entity.initialize]
    C --> D[Entity.addComponent]
    D --> E[Component.onAdd]
    E --> F{匹配Group?}
    F -->|是| G[Group.handleEvent]
    F -->|否| H[完成]
    G --> I{配置Collector?}
    I -->|是| J[Collector响应]
    I -->|否| H
    J --> H
    
    style A fill:#90EE90
    style H fill:#FFB6C1

系统执行流程

flowchart LR
    A[TimeManager.update] --> B[Core Channel]
    B --> C[Logic Channel]
    C --> D[Update Channel]
    D --> E[Render Channel]
    E --> F[Clear Channel]
    
    B --> B1[系统1]
    B --> B2[系统2]
    C --> C1[系统3]
    D --> D1[系统4]
    D --> D2[系统5]
    E --> E1[系统6]
    F --> F1[系统7]
    
    style A fill:#FFE4B5
    style B fill:#E0FFFF
    style C fill:#E0FFFF
    style D fill:#E0FFFF
    style E fill:#E0FFFF
    style F fill:#E0FFFF

关键接口说明

IMatcher (匹配器)

  • allOf(...components): 必须包含所有指定组件
  • anyOf(...components): 必须包含任一指定组件
  • noneOf(...components): 不能包含任一指定组件
  • extraOf(...components): 额外包含的组件(用于监听变化)

IGroup (实体组)

  • entities: 匹配的实体列表
  • component(id): 通过ID获取组件(需要配置componentGetter)
  • sort(priorityCompare): 按优先级排序

ICollector (响应收集器)

  • onEntityAdd: 实体添加时触发
  • onEntityRemove: 实体移除时触发
  • onComponentAdd: 组件添加时触发
  • onComponentRemove: 组件移除时触发

TimeChannel (时间通道)

  • Core: 核心周期,与世界更新频率同步
  • Logic: 逻辑周期,固定时间间隔更新
  • Update: 绘制周期,非固定时间间隔
  • Render: 渲染周期
  • Clear: 清理周期

使用示例

创建系统

@ecs.system({ world: "battle" })
export class SpawnSystem extends ecs.System<BattleWorldType> {
    protected getMatchers() {
        return {
            units: this.getMatcher(sg.SceneNodeEntity, true, Unit, Movement)
        };
    }
    
    onUpdate(deltaTime: float): void {
        this.groups.units.forEach(entity => {
            const unit = entity.getComponent(Unit)!;
            const movement = entity.getComponent(Movement)!;
            // 处理逻辑
        });
    }
}

创建实体

const context = world.context(sg.SceneNodeEntity);
const entity = context.createEntity(true);
entity.addComponent(Unit);
entity.addComponent(Movement);

使用匹配器

const matcher = context.matcher(true, Unit, Movement)
    .allOf(Unit, Movement)  // 必须同时有Unit和Movement
    .noneOf(Dead);          // 不能有Dead组件
const group = context.group(matcher);