diff --git a/README.md b/README.md
index 9c2e2dea..6b0ad2e4 100644
--- a/README.md
+++ b/README.md
@@ -19,16 +19,154 @@ TypeScript ECS (Entity-Component-System) 框架,专为游戏开发设计。
-## ECS 架构原理
+## 架构原理
-
-

-
+ECS Framework 采用多World + 多Scene的现代化架构设计:
-ECS 是一种基于组合而非继承的软件架构模式:
-- **Entity(实体)**: 游戏对象的唯一标识
-- **Component(组件)**: 纯数据结构,描述实体属性
-- **System(系统)**: 处理具有特定组件的实体
+```mermaid
+graph TD
+ subgraph Main["🎮 ECS Framework - 多World・多Scene架构"]
+ direction TB
+
+ subgraph CoreLayer["⚙️ 核心层 (Core Foundation)"]
+ direction LR
+ Core["🔧 Core
📋 生命周期管理
⚙️ 配置系统
🔗 平台兼容"]
+ Registry["📝 ComponentRegistry
🏷️ 类型注册
✨ 装饰器支持
🔒 类型安全"]
+ Pool["🔢 IdentifierPool
🆔 实体ID分配
♻️ ID回收
📊 BigInt兼容"]
+ PoolMgr["♻️ PoolManager
🎯 对象池
⚡ 内存优化
📈 性能提升"]
+ EventBus["📡 EventBus
🔄 事件系统
⚡ 异步/同步
🎭 类型安全"]
+ end
+
+ subgraph WorldLayer["🌍 世界管理层 (World Management)"]
+ direction TB
+ WorldMgr["🗺️ WorldManager
🚀 多World调度
📊 资源管理
🔍 统计监控
🧹 自动清理"]
+
+ subgraph WorldsContainer["多World容器"]
+ direction LR
+ World1["🌐 GameWorld
🎮 游戏逻辑
🌟 全局系统
🔄 跨Scene业务"]
+ World2["🌐 UIWorld
🎨 界面管理
⚡ 独立更新
🔒 资源隔离"]
+ end
+
+ GlobalSys["🎭 Global Systems
🌐 NetworkSync
👥 PlayerMgmt
📡 跨Scene通信"]
+ end
+
+ subgraph SceneLayer["🎬 场景层 (Scene Management)"]
+ direction LR
+ Scene1["🎯 BattleScene
⚔️ 实体管理
🎪 系统调度
⚡ 高性能处理"]
+ Scene2["🎯 MenuScene
🎨 界面逻辑
🔄 生命周期
💾 状态管理"]
+ Scene3["🎯 UIScene
📦 组件存储
🔍 查询引擎
🎭 交互处理"]
+ end
+
+ subgraph ECLayer["🤖 实体组件层 (Entity-Component System)"]
+ direction TB
+
+ subgraph EntityMgmt["📦 实体管理 (Entity Management)"]
+ direction LR
+ EntityMgr["👥 EntityManager
📋 集合管理
🌳 层次结构
⚡ 高效操作"]
+ Entities["🎭 Entities
👤 Player
👹 Enemy
💥 Bullet
🎯 轻量容器"]
+ end
+
+ subgraph ComponentStore["🧩 组件存储 (Component Storage)"]
+ direction LR
+ Storage["💾 ComponentStorage
📊 SoA模式
📚 AoS模式
⚡ 内存优化"]
+ StorageMgr["🗄️ StorageManager
🏷️ 类型管理
🔄 脏标记
📈 性能监控"]
+ Components["🎲 Components
📍 Position
🏃 Velocity
❤️ Health
📊 纯数据"]
+ end
+ end
+
+ subgraph SystemLayer["⚡ 系统层 (System Processing)"]
+ direction TB
+
+ subgraph EntitySys["🔄 实体系统 (Entity Systems)"]
+ direction LR
+ EntitySystems["🎪 EntitySystems
🏃 MovementSystem
🎨 RenderSystem
🧠 AISystem
⚡ 业务逻辑"]
+ Processors["📋 EntityProcessors
🎯 调度管理
📊 优先级
⚡ 批量处理"]
+ end
+ end
+
+ subgraph QueryLayer["🔍 查询优化层 (Query & Optimization)"]
+ direction LR
+ Matcher["🎯 Matcher
✅ withAll
🔄 withAny
❌ withNone
🌊 流式API
💾 智能缓存"]
+ QuerySys["🔎 QuerySystem
⚡ 实时查询
📦 批量优化
🔄 自动更新"]
+ Archetype["🏗️ ArchetypeSystem
📊 组件分组
🎯 原型缓存
💻 BitSet优化"]
+ end
+
+ subgraph DebugLayer["📊 监控调试层 (Debug & Monitoring)"]
+ direction LR
+ Debug["🐛 DebugManager
🌐 WebSocket调试
🎮 Cocos Creator插件
📸 内存快照"]
+ Perf["📈 PerformanceMonitor
📊 性能统计
⚠️ 阈值告警
📱 实时监控"]
+ Logger["📋 Logger
📊 分级日志
🎨 彩色输出
🔧 自定义处理器"]
+ end
+ end
+
+ %% 连接关系 - 使用更丰富的箭头样式
+ Core -.->|初始化| WorldMgr
+ Core -.->|注册| Registry
+ Core -.->|分配| Pool
+ Core -.->|管理| PoolMgr
+ Core -.->|事件| EventBus
+
+ WorldMgr ==>|调度| World1
+ WorldMgr ==>|调度| World2
+ World1 -.->|管理| GlobalSys
+
+ World1 ==>|包含| Scene1
+ World1 ==>|包含| Scene2
+ World2 ==>|包含| Scene3
+
+ Scene1 -->|使用| EntityMgr
+ Scene2 -->|使用| EntityMgr
+ Scene3 -->|使用| EntityMgr
+
+ EntityMgr -->|管理| Entities
+ Entities -->|附加| Components
+
+ Scene1 -->|存储| Storage
+ Scene2 -->|存储| Storage
+ Scene3 -->|存储| Storage
+ Storage -->|管理| StorageMgr
+
+ Scene1 -->|调度| EntitySystems
+ Scene2 -->|调度| EntitySystems
+ Scene3 -->|调度| EntitySystems
+ EntitySystems -->|处理| Processors
+
+ EntitySystems -->|查询| Matcher
+ Matcher -->|缓存| QuerySys
+ QuerySys -->|优化| Archetype
+
+ Core -.->|调试| Debug
+ Core -.->|监控| Perf
+ Core -.->|日志| Logger
+
+ %% 样式定义 - 使用Mermaid支持的语法
+ classDef coreStyle fill:#E3F2FD,stroke:#1976D2,stroke-width:3px,color:#0D47A1
+ classDef worldStyle fill:#F3E5F5,stroke:#7B1FA2,stroke-width:3px,color:#4A148C
+ classDef sceneStyle fill:#FFF3E0,stroke:#F57C00,stroke-width:3px,color:#E65100
+ classDef entityStyle fill:#E8F5E8,stroke:#388E3C,stroke-width:3px,color:#1B5E20
+ classDef systemStyle fill:#FCE4EC,stroke:#C2185B,stroke-width:3px,color:#880E4F
+ classDef queryStyle fill:#E0F2F1,stroke:#00695C,stroke-width:3px,color:#004D40
+ classDef debugStyle fill:#FFF8E1,stroke:#F9A825,stroke-width:3px,color:#FF8F00
+
+ class Core,Registry,Pool,PoolMgr,EventBus coreStyle
+ class WorldMgr,World1,World2,GlobalSys worldStyle
+ class Scene1,Scene2,Scene3 sceneStyle
+ class EntityMgr,Entities,Storage,StorageMgr,Components entityStyle
+ class EntitySystems,Processors systemStyle
+ class Matcher,QuerySys,Archetype queryStyle
+ class Debug,Perf,Logger debugStyle
+```
+
+### 核心概念
+
+| 概念 | 职责 | 特点 |
+|------|------|------|
+| **Entity** | 游戏对象唯一标识 | 轻量级容器,无业务逻辑 |
+| **Component** | 纯数据结构 | 描述实体属性,支持SoA优化 |
+| **System** | 业务逻辑处理 | 操作组件数据,可热插拔 |
+| **Scene** | 实体和系统容器 | 独立的游戏场景 |
+| **World** | Scene和全局系统容器 | 支持跨Scene的全局逻辑 |
+| **WorldManager** | 多World管理 | 统一调度和资源管理 |
## 特性
@@ -201,11 +339,20 @@ class GameSystem {
### SoA 存储优化
-
-

-
+针对大规模实体处理的内存布局优化:
-用于大规模实体处理:
+| 存储方式 | 内存布局 | 适用场景 | 性能特点 |
+|----------|----------|----------|----------|
+| **AoS** (Array of Structures) | `[{x,y,z}, {x,y,z}, {x,y,z}]` | 通用场景 | 访问灵活,缓存效率一般 |
+| **SoA** (Structure of Arrays) | `{x:[1,2,3], y:[4,5,6], z:[7,8,9]}` | 批量处理 | SIMD优化,缓存友好 |
+
+**SoA 优势:**
+- 🚀 提升 2-4x 批量处理性能
+- 💾 更好的CPU缓存利用率
+- 🔧 支持SIMD向量化操作
+- ⚡ 减少内存访问跳跃
+
+用法示例:
```typescript
import { EnableSoA, Float32, Int32 } from '@esengine/ecs-framework';
diff --git a/assets/svg/ecs-architecture.svg b/assets/svg/ecs-architecture.svg
deleted file mode 100644
index 09c8aef6..00000000
--- a/assets/svg/ecs-architecture.svg
+++ /dev/null
@@ -1,382 +0,0 @@
-
\ No newline at end of file
diff --git a/assets/svg/soa-vs-aos.svg b/assets/svg/soa-vs-aos.svg
deleted file mode 100644
index 9ffd2f57..00000000
--- a/assets/svg/soa-vs-aos.svg
+++ /dev/null
@@ -1,273 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/core-concepts.md b/docs/core-concepts.md
index 90d320dc..20e8aee5 100644
--- a/docs/core-concepts.md
+++ b/docs/core-concepts.md
@@ -14,7 +14,7 @@ ECS 架构将传统的面向对象设计分解为三个核心部分:
## Core(核心)
-Core 是框架的核心管理类,负责游戏的生命周期管理。
+Core 是框架的核心管理类,负责游戏的生命周期管理。框架采用融合设计,既支持传统的单Scene模式(向后兼容),也支持高级的多World/多Scene架构。
### 创建和配置
@@ -47,6 +47,40 @@ const core2 = Core.create(false); // 发布模式
const core3 = Core.create(); // 默认调试模式
```
+### 场景管理API
+
+```typescript
+// 单Scene模式(默认,向后兼容)
+const scene = new Scene();
+Core.setScene(scene); // 设置场景
+const currentScene = Core.getScene(); // 获取当前场景
+
+// 多World模式(高级功能)
+Core.enableWorldManager(); // 启用World管理器
+const worldManager = Core.getWorldManager();
+
+// 创建World
+const gameWorld = worldManager.createWorld('GameWorld', {
+ name: 'GameWorld',
+ maxScenes: 10,
+ autoCleanup: true
+});
+
+// 在World中管理Scene
+const battleScene = gameWorld.createScene('battle', new Scene());
+const uiScene = gameWorld.createScene('ui', new Scene());
+
+gameWorld.setSceneActive('battle', true);
+gameWorld.setSceneActive('ui', true);
+
+// 启动World
+gameWorld.start();
+
+// 获取World统计
+const worldStats = gameWorld.getStats();
+console.log('World状态:', worldStats);
+```
+
### 事件系统
```typescript
@@ -404,6 +438,235 @@ console.log("实体数量:", stats.entityCount);
console.log("系统数量:", stats.processorCount);
```
+## World(世界)
+
+World是Scene的容器,提供了更高级的场景管理功能。每个World可以包含多个Scene,适用于复杂的游戏架构。
+
+### World基本使用
+
+```typescript
+import { World, Scene, IWorldConfig } from '@esengine/ecs-framework';
+
+// 创建World配置
+const worldConfig: IWorldConfig = {
+ name: 'GameWorld',
+ debug: true,
+ maxScenes: 10,
+ autoCleanup: true
+};
+
+// 创建World
+const gameWorld = new World(worldConfig);
+
+// 在World中创建Scene
+const battleScene = gameWorld.createScene('battle', new Scene());
+const uiScene = gameWorld.createScene('ui', new Scene());
+const menuScene = gameWorld.createScene('menu');
+
+// 激活Scene
+gameWorld.setSceneActive('battle', true);
+gameWorld.setSceneActive('ui', true);
+
+// 启动World
+gameWorld.start();
+```
+
+### World生命周期管理
+
+```typescript
+// 启动World(启动所有全局System)
+gameWorld.start();
+
+// 检查World状态
+if (gameWorld.isActive) {
+ console.log('World正在运行');
+}
+
+// 停止World(停止所有Scene和全局System)
+gameWorld.stop();
+
+// 销毁World(清理所有资源)
+gameWorld.destroy();
+```
+
+### Scene管理
+
+```typescript
+// 获取Scene
+const battleScene = gameWorld.getScene('battle');
+
+// 检查Scene是否激活
+if (gameWorld.isSceneActive('battle')) {
+ console.log('战斗场景正在运行');
+}
+
+// 移除Scene
+gameWorld.removeScene('menu');
+
+// 获取所有Scene ID
+const sceneIds = gameWorld.getSceneIds();
+console.log('所有Scene:', sceneIds);
+
+// 获取活跃Scene数量
+const activeCount = gameWorld.getActiveSceneCount();
+console.log('活跃Scene数量:', activeCount);
+```
+
+### 全局System管理
+
+World支持全局System,这些System会在所有Scene之前执行,适用于跨Scene的业务逻辑:
+
+```typescript
+import { IGlobalSystem } from '@esengine/ecs-framework';
+
+// 全局网络同步系统
+class GlobalNetworkSystem implements IGlobalSystem {
+ public readonly name = 'GlobalNetworkSystem';
+
+ public initialize(): void {
+ // 初始化网络连接
+ console.log('网络系统初始化');
+ }
+
+ public update(): void {
+ // 处理全局网络同步逻辑
+ // 注意:全局系统处理的是World级别的逻辑,不直接处理实体
+ // 如需处理特定实体,请在Scene中使用EntitySystem
+ this.syncGlobalNetworkState();
+ }
+
+ public reset(): void {
+ // 重置系统状态
+ }
+
+ public destroy(): void {
+ // 清理网络连接
+ console.log('网络系统销毁');
+ }
+
+ private syncGlobalNetworkState(): void {
+ // 全局网络状态同步
+ }
+}
+
+// 添加全局System
+const networkSystem = gameWorld.addGlobalSystem(new GlobalNetworkSystem());
+
+// 获取全局System
+const existingSystem = gameWorld.getGlobalSystem(GlobalNetworkSystem);
+
+// 移除全局System
+gameWorld.removeGlobalSystem(networkSystem);
+```
+
+> **注意**:全局System适用于World级别的业务逻辑(如网络管理、资源管理、全局状态管理等)。如果需要处理具体的实体和组件,请在Scene中使用EntitySystem。
+
+### World状态监控
+
+```typescript
+// 获取World状态
+const status = gameWorld.getStatus();
+console.log('World状态:', {
+ name: status.name,
+ isActive: status.isActive,
+ sceneCount: status.sceneCount,
+ activeSceneCount: status.activeSceneCount,
+ globalSystemCount: status.globalSystemCount,
+ scenes: status.scenes
+});
+
+// 获取World统计信息
+const stats = gameWorld.getStats();
+console.log('World统计:', {
+ totalEntities: stats.totalEntities,
+ totalSystems: stats.totalSystems,
+ memoryUsage: stats.memoryUsage
+});
+```
+
+## WorldManager(世界管理器)
+
+WorldManager是单例模式的World管理器,负责管理多个World实例。
+
+### WorldManager基本使用
+
+```typescript
+import { WorldManager, IWorldManagerConfig } from '@esengine/ecs-framework';
+
+// 获取WorldManager实例
+const worldManager = WorldManager.getInstance({
+ maxWorlds: 50,
+ autoCleanup: true,
+ debug: true
+});
+
+// 或者通过Core获取
+Core.enableWorldManager();
+const worldManager2 = Core.getWorldManager();
+```
+
+### World管理
+
+```typescript
+// 创建World
+const gameWorld = worldManager.createWorld('GameRoom_001', {
+ name: 'GameRoom_001',
+ maxScenes: 5,
+ autoCleanup: true
+});
+
+// 获取World
+const existingWorld = worldManager.getWorld('GameRoom_001');
+
+// 检查World是否存在
+if (worldManager.getWorld('GameRoom_001')) {
+ console.log('World存在');
+}
+
+// 销毁World
+worldManager.removeWorld('GameRoom_001');
+
+// 获取所有World ID
+const worldIds = worldManager.getWorldIds();
+console.log('所有World ID:', worldIds);
+
+// 获取活跃World
+const activeWorlds = worldManager.getActiveWorlds();
+console.log('活跃World数量:', activeWorlds.length);
+```
+
+### WorldManager统计和监控
+
+```typescript
+// 获取WorldManager状态
+const managerStatus = worldManager.getStatus();
+console.log('WorldManager状态:', {
+ totalWorlds: managerStatus.totalWorlds,
+ activeWorlds: managerStatus.activeWorlds,
+ maxWorlds: managerStatus.maxWorlds,
+ memoryUsage: managerStatus.memoryUsage
+});
+
+// 获取所有World的统计
+const allStats = worldManager.getAllWorldStats();
+allStats.forEach(stat => {
+ console.log(`World ${stat.worldName}:`, stat);
+});
+
+// 清理空闲World
+const cleanedCount = worldManager.cleanup();
+console.log(`清理了 ${cleanedCount} 个空闲World`);
+```
+
+### 使用场景
+
+World和WorldManager适用于:
+- **游戏服务器**:每个房间一个独立World
+- **复杂客户端**:按功能分层管理Scene(游戏层、UI层、特效层)
+- **并发世界**:需要同时运行多个独立游戏世界的场景
+
+> **完整示例和最佳实践**:查看 [场景管理完整指南](scene-management-guide.md#world多场景管理) 了解详细的实现方案和架构设计
+
## System(系统)
系统处理实体集合,实现游戏的核心逻辑。
@@ -646,11 +909,18 @@ const movingEntities = scene.querySystem.queryAll(PositionComponent, VelocityCom
ECS Framework 提供了完整的实体组件系统架构:
-- **Core** 管理游戏生命周期和全局功能
+- **Core** 管理游戏生命周期和全局功能,支持单Scene和多World模式
- **Entity** 作为游戏对象的基础容器
- **Component** 实现具体的功能模块,支持对象池优化
- **System** 处理游戏逻辑
- **Scene** 管理游戏世界状态,支持批量操作
+- **World** 高级场景容器,支持多Scene管理和全局System
+- **WorldManager** 管理多个World实例,适用于复杂架构
- **高级优化** 位掩码优化器、组件对象池、批量操作等
-通过合理使用这些核心概念和优化功能,可以构建出高性能、结构清晰、易于维护的游戏代码。
\ No newline at end of file
+### 架构选择指南
+
+- **单Scene模式**:适合简单游戏、单机游戏、原型开发
+- **多World模式**:适合多人游戏服务器、复杂应用、需要场景隔离的项目
+
+框架采用融合设计,确保向后兼容性的同时提供强大的扩展能力。通过合理使用这些核心概念和优化功能,可以构建出高性能、结构清晰、易于维护的游戏代码。
\ No newline at end of file
diff --git a/docs/getting-started.md b/docs/getting-started.md
index 2bb96aea..08a1f2cc 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -33,7 +33,7 @@ Core.update(deltaTime);
### 基础配置
-ECS框架提供了灵活的配置选项来满足不同项目需求:
+ECS框架提供了灵活的配置选项来满足不同项目需求。框架采用融合设计,既支持传统的单Scene模式(向后兼容),也支持高级的多World/多Scene架构:
```typescript
import { Core, ICoreConfig } from '@esengine/ecs-framework';
@@ -65,6 +65,31 @@ const config: ICoreConfig = {
const core = Core.create(config);
```
+### 架构说明
+
+ECS框架支持两种使用模式:
+
+1. **单Scene模式(默认,向后兼容)**:
+ ```typescript
+ // 传统用法,无需任何修改
+ const scene = new Scene();
+ Core.setScene(scene);
+ ```
+
+2. **多World模式(高级功能)**:
+ ```typescript
+ // 启用World管理器,支持多World/多Scene架构
+ Core.enableWorldManager();
+ const roomWorld = Core.getWorldManager().createWorld('Room_001');
+ const battleScene = roomWorld.createScene('battle');
+ ```
+
+**使用场景:**
+- **单Scene模式**:适合简单游戏、单机游戏、原型开发
+- **多World模式**:适合多人游戏服务器、复杂应用、需要场景隔离的项目
+
+> **详细了解World系统**:查看 [场景管理完整指南](scene-management-guide.md) 获取完整的多World架构示例和最佳实践
+
### 调试功能
ECS框架内置了强大的调试功能,支持运行时监控和远程调试:
@@ -324,7 +349,7 @@ class CocosRenderSystem extends EntitySystem {
### Node.js后端
```typescript
-import { Core, Scene, EntityManager, EntitySystem, Time } from '@esengine/ecs-framework';
+import { Core, Scene, EntityManager, EntitySystem, Time, World } from '@esengine/ecs-framework';
class ServerGameManager {
private scene: Scene;
@@ -338,6 +363,7 @@ class ServerGameManager {
Core.create(true); // 启用调试模式
// 完整配置示例: Core.create({ debug: true, enableEntitySystems: true, debugConfig: {...} })
+ // 单Scene模式(简单场景)
this.scene = new Scene();
this.scene.name = "ServerScene";
Core.setScene(this.scene);
@@ -418,6 +444,8 @@ const server = new ServerGameManager();
server.start();
```
+> **多房间游戏服务器示例**:查看 [场景管理完整指南](scene-management-guide.md#world多场景管理) 了解如何使用多World架构实现复杂的多房间游戏服务器
+
### 原生浏览器
```typescript
diff --git a/docs/scene-management-guide.md b/docs/scene-management-guide.md
index a8a3d1fc..5b52091a 100644
--- a/docs/scene-management-guide.md
+++ b/docs/scene-management-guide.md
@@ -1,6 +1,6 @@
# 场景管理完整指南
-场景(Scene)是ECS框架中管理游戏对象和系统的核心容器。本指南将详细介绍如何有效地使用场景来构建和管理你的游戏。
+场景(Scene)是ECS框架中管理游戏对象和系统的核心容器。框架采用融合设计,既支持传统的单Scene模式(向后兼容),也支持高级的多World/多Scene架构。本指南将详细介绍如何有效地使用场景来构建和管理你的游戏。
## 场景基础概念
@@ -25,6 +25,47 @@ Core.setScene(gameScene);
> **注意**: `Core.scene = ` 设置方式已被标记为废弃,推荐使用 `Core.setScene()` 方法。新方法提供更好的类型安全性和可预测的激活时序。
+### 架构选择指南
+
+ECS框架提供两种使用模式:
+
+#### 1. 单Scene模式(默认,向后兼容)
+
+```typescript
+// 传统用法,无需任何修改
+const scene = new Scene();
+Core.setScene(scene);
+```
+
+**适用场景:**
+- 简单游戏、单机游戏
+- 原型开发、快速验证
+- 学习ECS架构
+- 不需要复杂场景管理的项目
+
+#### 2. 多World模式(高级功能)
+
+```typescript
+// 启用World管理器
+Core.enableWorldManager();
+const worldManager = Core.getWorldManager();
+
+// 创建多个World,每个World可包含多个Scene
+const roomWorld = worldManager.createWorld('Room_001');
+const battleScene = roomWorld.createScene('battle');
+const uiScene = roomWorld.createScene('ui');
+
+roomWorld.start();
+roomWorld.setSceneActive('battle', true);
+roomWorld.setSceneActive('ui', true);
+```
+
+**适用场景:**
+- 多人游戏服务器(每个房间一个World)
+- 复杂应用架构(需要场景隔离)
+- 需要并发处理多个游戏世界
+- 高级场景管理需求
+
### 场景的生命周期
```typescript
@@ -214,9 +255,374 @@ class GameScene extends Scene {
}
```
-## 场景切换和管理
+## World多场景管理
-### 1. 场景管理器
+### 1. World基础使用
+
+对于需要复杂场景管理的项目,可以使用World系统:
+
+```typescript
+import { Core, World, Scene, WorldManager, IGlobalSystem } from '@esengine/ecs-framework';
+
+// 定义全局系统(跨Scene的业务逻辑)
+class NetworkSyncSystem implements IGlobalSystem {
+ public readonly name = 'NetworkSyncSystem';
+
+ public initialize(): void {
+ console.log('网络同步系统初始化');
+ }
+
+ public update(): void {
+ // 同步所有Scene的网络状态
+ this.syncNetworkData();
+ }
+
+ public reset(): void {
+ // 重置网络连接
+ }
+
+ public destroy(): void {
+ console.log('网络同步系统销毁');
+ }
+
+ private syncNetworkData(): void {
+ // 网络数据同步逻辑
+ }
+}
+
+class PlayerManagementSystem implements IGlobalSystem {
+ public readonly name = 'PlayerManagementSystem';
+
+ public initialize(): void {
+ console.log('玩家管理系统初始化');
+ }
+
+ public update(): void {
+ // 管理跨Scene的玩家数据
+ this.managePlayerStates();
+ }
+
+ public reset(): void {
+ // 重置玩家状态
+ }
+
+ public destroy(): void {
+ console.log('玩家管理系统销毁');
+ }
+
+ private managePlayerStates(): void {
+ // 玩家状态管理逻辑
+ }
+}
+
+// 启用World管理功能
+Core.enableWorldManager();
+const worldManager = Core.getWorldManager();
+
+// 创建游戏房间World
+const roomWorld = worldManager.createWorld('GameRoom_001', {
+ name: 'GameRoom_001',
+ maxScenes: 5,
+ autoCleanup: true,
+ debug: true
+});
+
+// 在World中创建多个Scene
+const gameScene = roomWorld.createScene('game', new GameScene());
+const uiScene = roomWorld.createScene('ui', new UIScene());
+const backgroundScene = roomWorld.createScene('background', new BackgroundScene());
+
+// 添加全局系统(跨Scene的系统)
+roomWorld.addGlobalSystem(new NetworkSyncSystem());
+roomWorld.addGlobalSystem(new PlayerManagementSystem());
+
+// 启动World并激活Scene
+roomWorld.start();
+roomWorld.setSceneActive('game', true);
+roomWorld.setSceneActive('ui', true);
+roomWorld.setSceneActive('background', true);
+```
+
+### 2. 多房间游戏服务器示例
+
+```typescript
+// 房间管理系统
+class RoomManagementSystem implements IGlobalSystem {
+ public readonly name = 'RoomManagementSystem';
+ private roomId: string;
+
+ constructor(roomId: string) {
+ this.roomId = roomId;
+ }
+
+ public initialize(): void {
+ console.log(`房间管理系统初始化: ${this.roomId}`);
+ }
+
+ public update(): void {
+ // 管理房间状态、玩家进出等
+ this.manageRoomState();
+ }
+
+ public reset(): void {
+ // 重置房间状态
+ }
+
+ public destroy(): void {
+ console.log(`房间管理系统销毁: ${this.roomId}`);
+ }
+
+ private manageRoomState(): void {
+ // 房间状态管理逻辑
+ }
+}
+
+// 玩家同步系统
+class PlayerSyncSystem implements IGlobalSystem {
+ public readonly name = 'PlayerSyncSystem';
+
+ public initialize(): void {
+ console.log('玩家同步系统初始化');
+ }
+
+ public update(): void {
+ // 同步房间内所有玩家的状态
+ this.syncPlayerData();
+ }
+
+ public reset(): void {
+ // 重置同步状态
+ }
+
+ public destroy(): void {
+ console.log('玩家同步系统销毁');
+ }
+
+ private syncPlayerData(): void {
+ // 玩家数据同步逻辑
+ }
+}
+
+class MultiRoomGameServer {
+ private worldManager: WorldManager;
+ private rooms: Map = new Map();
+
+ constructor() {
+ Core.create({ debug: false });
+ Core.enableWorldManager();
+ this.worldManager = Core.getWorldManager();
+ }
+
+ // 创建游戏房间
+ createRoom(roomId: string): World {
+ const roomWorld = this.worldManager.createWorld(`Room_${roomId}`, {
+ name: `GameRoom_${roomId}`,
+ maxScenes: 3,
+ autoCleanup: true
+ });
+
+ // 房间内的Scene设置
+ const gameScene = roomWorld.createScene('game', new ServerGameScene());
+ const lobbyScene = roomWorld.createScene('lobby', new LobbyScene());
+
+ // 设置房间级的全局系统
+ roomWorld.addGlobalSystem(new RoomManagementSystem(roomId));
+ roomWorld.addGlobalSystem(new PlayerSyncSystem());
+
+ // 启动房间
+ roomWorld.start();
+ roomWorld.setSceneActive('lobby', true); // 默认激活大厅
+
+ this.rooms.set(roomId, roomWorld);
+ console.log(`创建房间: ${roomId}`);
+
+ return roomWorld;
+ }
+
+ // 开始游戏
+ startGame(roomId: string): boolean {
+ const roomWorld = this.rooms.get(roomId);
+ if (!roomWorld) return false;
+
+ // 停用大厅,激活游戏Scene
+ roomWorld.setSceneActive('lobby', false);
+ roomWorld.setSceneActive('game', true);
+
+ console.log(`房间 ${roomId} 开始游戏`);
+ return true;
+ }
+
+ // 销毁房间
+ destroyRoom(roomId: string): boolean {
+ const roomWorld = this.rooms.get(roomId);
+ if (!roomWorld) return false;
+
+ roomWorld.destroy();
+ this.rooms.delete(roomId);
+ console.log(`销毁房间: ${roomId}`);
+ return true;
+ }
+
+ // 获取服务器状态
+ getServerStats() {
+ return {
+ totalRooms: this.rooms.size,
+ activeWorlds: this.worldManager.getActiveWorlds().length,
+ rooms: Array.from(this.rooms.keys()).map(roomId => ({
+ roomId,
+ world: this.rooms.get(roomId)?.getStatus()
+ }))
+ };
+ }
+
+ // 游戏循环
+ start(): void {
+ const gameLoop = () => {
+ const deltaTime = 1000 / 60; // 60 TPS
+ Core.update(deltaTime / 1000);
+ setTimeout(gameLoop, deltaTime);
+ };
+ gameLoop();
+ }
+}
+
+// 使用示例
+const gameServer = new MultiRoomGameServer();
+gameServer.start();
+
+// 创建房间
+const room1 = gameServer.createRoom('room_001');
+const room2 = gameServer.createRoom('room_002');
+
+// 开始游戏
+setTimeout(() => {
+ gameServer.startGame('room_001');
+}, 5000);
+
+console.log('服务器状态:', gameServer.getServerStats());
+```
+
+### 3. 客户端多Scene管理示例
+
+```typescript
+class GameClient {
+ private worldManager: WorldManager;
+ private mainWorld: World;
+
+ constructor() {
+ Core.create({ debug: true });
+ Core.enableWorldManager();
+ this.worldManager = Core.getWorldManager();
+
+ this.setupGameWorld();
+ }
+
+ private setupGameWorld(): void {
+ // 创建主游戏世界
+ this.mainWorld = this.worldManager.createWorld('MainWorld', {
+ name: 'ClientWorld',
+ maxScenes: 10,
+ autoCleanup: false // 客户端通常不需要自动清理
+ });
+
+ // 创建不同层级的Scene
+ this.createGameplayScenes();
+ this.createUIScenes();
+ this.createEffectScenes();
+
+ // 启动世界
+ this.mainWorld.start();
+ this.activateDefaultScenes();
+ }
+
+ private createGameplayScenes(): void {
+ // 游戏主场景
+ const gameScene = this.mainWorld.createScene('gameplay', new GameplayScene());
+
+ // 背景场景
+ const backgroundScene = this.mainWorld.createScene('background', new BackgroundScene());
+
+ // 特效场景
+ const effectsScene = this.mainWorld.createScene('effects', new EffectsScene());
+ }
+
+ private createUIScenes(): void {
+ // 主UI场景
+ const mainUIScene = this.mainWorld.createScene('mainUI', new MainUIScene());
+
+ // 菜单场景
+ const menuScene = this.mainWorld.createScene('menu', new MenuScene());
+
+ // 设置场景
+ const settingsScene = this.mainWorld.createScene('settings', new SettingsScene());
+ }
+
+ private createEffectScenes(): void {
+ // 粒子效果场景
+ const particleScene = this.mainWorld.createScene('particles', new ParticleScene());
+
+ // 音效场景
+ const audioScene = this.mainWorld.createScene('audio', new AudioScene());
+ }
+
+ private activateDefaultScenes(): void {
+ // 激活基础Scene
+ this.mainWorld.setSceneActive('background', true);
+ this.mainWorld.setSceneActive('gameplay', true);
+ this.mainWorld.setSceneActive('mainUI', true);
+ this.mainWorld.setSceneActive('particles', true);
+ this.mainWorld.setSceneActive('audio', true);
+
+ // 菜单和设置默认不激活
+ this.mainWorld.setSceneActive('menu', false);
+ this.mainWorld.setSceneActive('settings', false);
+ }
+
+ // 切换到菜单
+ showMenu(): void {
+ this.mainWorld.setSceneActive('gameplay', false);
+ this.mainWorld.setSceneActive('menu', true);
+ }
+
+ // 切换回游戏
+ hideMenu(): void {
+ this.mainWorld.setSceneActive('menu', false);
+ this.mainWorld.setSceneActive('gameplay', true);
+ }
+
+ // 显示设置
+ showSettings(): void {
+ this.mainWorld.setSceneActive('settings', true);
+ }
+
+ // 隐藏设置
+ hideSettings(): void {
+ this.mainWorld.setSceneActive('settings', false);
+ }
+
+ // 获取World状态
+ getWorldStatus() {
+ return this.mainWorld.getStatus();
+ }
+}
+
+// 使用示例
+const gameClient = new GameClient();
+
+// 显示菜单
+gameClient.showMenu();
+
+// 5秒后返回游戏
+setTimeout(() => {
+ gameClient.hideMenu();
+}, 5000);
+
+console.log('客户端World状态:', gameClient.getWorldStatus());
+```
+
+## 传统场景切换和管理
+
+### 1. 单Scene模式场景管理器
> **注意:** 以下的 SceneManager、TransitionManager 等是自定义的场景管理类示例,不是ECS框架提供的内置API。你可以基于这些示例实现自己的场景管理系统。
@@ -731,6 +1137,47 @@ A:
### Q: 多个场景可以同时存在吗?
-A: 框架同时只支持一个活跃场景,但可以通过场景栈实现多场景管理(如暂停菜单)。
+A:
+- **单Scene模式**:框架同时只支持一个活跃场景,但可以通过场景栈实现多场景管理(如暂停菜单)
+- **多World模式**:每个World可以包含多个同时激活的Scene,支持复杂的多场景架构
-通过合理使用场景系统,你可以构建出结构清晰、性能优良的游戏架构!
\ No newline at end of file
+### Q: 什么时候使用World系统?
+
+A:
+- 多人游戏服务器(每个房间独立管理)
+- 需要并发运行多个独立游戏世界
+- 复杂的客户端架构(游戏层、UI层、特效层分离)
+- 需要跨Scene的全局系统支持
+
+### Q: World和Scene的性能影响?
+
+A:
+- **单Scene模式**:最佳性能,适合简单项目
+- **多World模式**:每个World独立更新,合理使用不会显著影响性能
+- **建议**:根据项目复杂度选择合适的架构
+
+### Q: 如何从单Scene迁移到多World?
+
+A:
+```typescript
+// 原始单Scene代码
+const scene = new Scene();
+Core.setScene(scene);
+
+// 迁移到World模式(可选)
+Core.enableWorldManager();
+const world = Core.getWorldManager().createWorld('MainWorld');
+const scene = world.createScene('main', new Scene());
+world.start();
+world.setSceneActive('main', true);
+```
+
+### Q: World系统的最佳实践?
+
+A:
+1. **服务器端**:每个游戏房间使用独立World
+2. **客户端**:按功能层级划分Scene(游戏、UI、特效)
+3. **全局系统**:将跨Scene的逻辑放在World的全局System中
+4. **资源管理**:使用World的autoCleanup功能自动清理空闲资源
+
+通过合理选择单Scene或多World架构,你可以构建出结构清晰、性能优良的游戏架构!
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 3bb20d62..4d6e9750 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11537,7 +11537,7 @@
},
"packages/core": {
"name": "@esengine/ecs-framework",
- "version": "2.1.44",
+ "version": "2.1.45",
"license": "MIT",
"devDependencies": {
"@rollup/plugin-commonjs": "^28.0.3",
diff --git a/packages/core/package.json b/packages/core/package.json
index be0ccb28..54ceeceb 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -1,6 +1,6 @@
{
"name": "@esengine/ecs-framework",
- "version": "2.1.44",
+ "version": "2.1.45",
"description": "用于Laya、Cocos Creator等JavaScript游戏引擎的高性能ECS框架",
"main": "bin/index.js",
"types": "bin/index.d.ts",
diff --git a/packages/core/src/Core.ts b/packages/core/src/Core.ts
index 6e98098f..2d94d5f2 100644
--- a/packages/core/src/Core.ts
+++ b/packages/core/src/Core.ts
@@ -6,8 +6,8 @@ import { Time } from './Utils/Time';
import { PerformanceMonitor } from './Utils/PerformanceMonitor';
import { PoolManager } from './Utils/Pool/PoolManager';
import { ECSFluentAPI, createECSAPI } from './ECS/Core/FluentAPI';
-import { Scene } from './ECS/Scene';
import { IScene } from './ECS/IScene';
+import { WorldManager } from './ECS/WorldManager';
import { DebugManager } from './Utils/Debug';
import { ICoreConfig, IECSDebugConfig } from './Types';
import { BigIntFactory, EnvironmentInfo } from './ECS/Utils/BigIntCompatibility';
@@ -46,6 +46,20 @@ export class Core {
* 当设置为true时,游戏循环将暂停执行。
*/
public static paused = false;
+
+ /**
+ * 默认World ID
+ *
+ * 用于单Scene模式的默认World标识
+ */
+ private static readonly DEFAULT_WORLD_ID = '__default__';
+
+ /**
+ * 默认Scene ID
+ *
+ * 用于单Scene模式的默认Scene标识
+ */
+ private static readonly DEFAULT_SCENE_ID = '__main__';
/**
* 全局核心实例
@@ -71,12 +85,6 @@ export class Core {
*/
public readonly debug: boolean;
- /**
- * 待切换的场景
- *
- * 存储下一帧要切换到的场景实例。
- */
- public _nextScene: IScene | null = null;
/**
* 全局管理器集合
@@ -113,10 +121,6 @@ export class Core {
*/
public _ecsAPI?: ECSFluentAPI;
- /**
- * 当前活动场景
- */
- public _scene?: IScene;
/**
* 调试管理器
@@ -125,6 +129,13 @@ export class Core {
*/
public _debugManager?: DebugManager;
+ /**
+ * World管理器
+ *
+ * 管理多个World实例,支持多房间/多世界架构。
+ */
+ public _worldManager?: WorldManager;
+
/**
* Core配置
*/
@@ -194,82 +205,63 @@ export class Core {
}
/**
- * 获取当前活动的场景
+ * 获取当前活动的场景(属性访问器)
*
* @returns 当前场景实例,如果没有则返回null
*/
public static get scene(): IScene | null {
- if (!this._instance)
- return null;
- return this._instance._scene || null;
+ return this.getScene();
}
/**
- * 设置当前场景(已废弃)
+ * 获取当前活动的场景(方法调用)
*
- * @deprecated 请使用 Core.setScene() 方法代替。scene setter 可能导致场景延迟激活的时序问题,
- * 而 setScene() 提供更好的类型安全性和可预测的激活时序。
- *
- * 迁移示例:
- * ```typescript
- * // 旧方式(已废弃)
- * Core.scene = myScene;
- *
- * // 新方式(推荐)
- * Core.setScene(myScene);
- * ```
- *
- * 如果当前没有场景,会立即切换;否则会在下一帧切换。
- *
- * @param value - 场景实例
+ * @returns 当前场景实例,如果没有则返回null
*/
- public static set scene(value: IScene | null) {
- if (!value) return;
-
- if (this._instance._scene == null) {
- this._instance.setSceneInternal(value);
- } else {
- this._instance._nextScene = value;
+ public static getScene(): T | null {
+ if (!this._instance) {
+ return null;
}
+
+ // 确保默认World存在
+ this._instance.ensureDefaultWorld();
+
+ const defaultWorld = this._instance._worldManager!.getWorld(this.DEFAULT_WORLD_ID);
+ return defaultWorld?.getScene(this.DEFAULT_SCENE_ID) as T || null;
}
+
/**
- * 类型安全的场景设置方法(推荐)
- *
- * 这是设置场景的推荐方法,提供更好的类型安全性和可预测的激活时序。
- * 相比于 scene setter,此方法能确保场景正确初始化和激活。
- *
- * 如果当前没有场景,会立即切换;否则会在下一帧切换。
+ * 设置当前场景
*
* @param scene - 要设置的场景实例
* @returns 设置的场景实例,便于链式调用
- *
- * @example
- * ```typescript
- * const myScene = new MyScene();
- * Core.setScene(myScene);
- *
- * // 链式调用
- * const scene = Core.setScene(new MyScene()).addSystem(new MySystem());
- * ```
*/
public static setScene(scene: T): T {
- if (this._instance._scene == null) {
- this._instance.setSceneInternal(scene);
- } else {
- this._instance._nextScene = scene;
+ if (!this._instance) {
+ throw new Error("Core实例未创建,请先调用Core.create()");
}
+
+ // 确保默认World存在
+ this._instance.ensureDefaultWorld();
+
+ const defaultWorld = this._instance._worldManager!.getWorld(this.DEFAULT_WORLD_ID)!;
+
+ // 移除旧的主Scene(如果存在)
+ if (defaultWorld.getScene(this.DEFAULT_SCENE_ID)) {
+ defaultWorld.removeScene(this.DEFAULT_SCENE_ID);
+ }
+
+ // 添加新Scene到默认World
+ defaultWorld.createScene(this.DEFAULT_SCENE_ID, scene);
+ defaultWorld.setSceneActive(this.DEFAULT_SCENE_ID, true);
+
+ // 触发场景切换回调
+ this._instance.onSceneChanged();
+
return scene;
}
- /**
- * 类型安全的场景获取方法
- *
- * @returns 当前场景实例
- */
- public static getScene(): T | null {
- return this._instance?._scene as T || null;
- }
/**
* 创建Core实例
@@ -466,15 +458,61 @@ export class Core {
}
/**
- * 内部场景设置方法
+ * 获取WorldManager实例
*
- * @param scene - 要设置的场景实例
+ * @returns WorldManager实例,如果未初始化则自动创建
*/
- private setSceneInternal(scene: IScene): void {
- this._scene = scene;
- this.onSceneChanged();
- this._scene.initialize();
- this._scene.begin();
+ public static getWorldManager(): WorldManager {
+ if (!this._instance) {
+ throw new Error("Core实例未创建,请先调用Core.create()");
+ }
+
+ if (!this._instance._worldManager) {
+ // 多World模式的配置(用户主动获取WorldManager)
+ this._instance._worldManager = WorldManager.getInstance({
+ maxWorlds: 50,
+ autoCleanup: true,
+ cleanupInterval: 60000,
+ debug: this._instance._config.debug
+ });
+ }
+
+ return this._instance._worldManager;
+ }
+
+ /**
+ * 启用World管理
+ *
+ * 显式启用World功能,用于多房间/多世界架构
+ */
+ public static enableWorldManager(): WorldManager {
+ return this.getWorldManager();
+ }
+
+ /**
+ * 确保默认World存在
+ *
+ * 内部方法,用于懒初始化默认World
+ */
+ private ensureDefaultWorld(): void {
+ if (!this._worldManager) {
+ this._worldManager = WorldManager.getInstance({
+ maxWorlds: 1, // 单场景用户只需要1个World
+ autoCleanup: false, // 单场景不需要自动清理
+ cleanupInterval: 0, // 禁用清理定时器
+ debug: this._config.debug
+ });
+ }
+
+ // 检查默认World是否存在
+ if (!this._worldManager.getWorld(Core.DEFAULT_WORLD_ID)) {
+ this._worldManager.createWorld(Core.DEFAULT_WORLD_ID, {
+ name: 'DefaultWorld',
+ maxScenes: 1,
+ autoCleanup: false
+ });
+ this._worldManager.setWorldActive(Core.DEFAULT_WORLD_ID, true);
+ }
}
/**
@@ -485,28 +523,19 @@ export class Core {
public onSceneChanged() {
Time.sceneChanged();
+ // 获取当前Scene(从默认World)
+ const currentScene = Core.getScene();
+
// 初始化ECS API(如果场景支持)
- if (this._scene && this._scene.querySystem && this._scene.eventSystem) {
- this._ecsAPI = createECSAPI(this._scene, this._scene.querySystem, this._scene.eventSystem);
+ if (currentScene && currentScene.querySystem && currentScene.eventSystem) {
+ this._ecsAPI = createECSAPI(currentScene, currentScene.querySystem, currentScene.eventSystem);
}
// 延迟调试管理器通知,避免在场景初始化过程中干扰属性
if (this._debugManager) {
- // 使用 requestAnimationFrame 确保在场景完全初始化后再收集数据
- if (typeof requestAnimationFrame !== 'undefined') {
- requestAnimationFrame(() => {
- if (this._debugManager) {
- this._debugManager.onSceneChanged();
- }
- });
- } else {
- // 兜底:使用 setTimeout
- setTimeout(() => {
- if (this._debugManager) {
- this._debugManager.onSceneChanged();
- }
- }, 0);
- }
+ queueMicrotask(() => {
+ this._debugManager?.onSceneChanged();
+ });
}
}
@@ -567,23 +596,25 @@ export class Core {
// 更新对象池管理器
this._poolManager.update();
- // 处理场景切换
- if (this._nextScene != null) {
- if (this._scene != null)
- this._scene.end();
+ // 更新所有World
+ if (this._worldManager) {
+ const worldsStartTime = this._performanceMonitor.startMonitoring('Worlds.update');
+ const activeWorlds = this._worldManager.getActiveWorlds();
+ let totalWorldEntities = 0;
- this._scene = this._nextScene;
- this._nextScene = null;
- this.onSceneChanged();
- this._scene.begin();
- }
+ for (const world of activeWorlds) {
+ // 更新World的全局System
+ world.updateGlobalSystems();
+
+ // 更新World中的所有Scene
+ world.updateScenes();
- // 更新当前场景
- if (this._scene != null && this._scene.update) {
- const sceneStartTime = this._performanceMonitor.startMonitoring('Scene.update');
- this._scene.update();
- const entityCount = this._scene.entities?.count || 0;
- this._performanceMonitor.endMonitoring('Scene.update', sceneStartTime, entityCount);
+ // 统计实体数量(用于性能监控)
+ const worldStats = world.getStats();
+ totalWorldEntities += worldStats.totalEntities;
+ }
+
+ this._performanceMonitor.endMonitoring('Worlds.update', worldsStartTime, totalWorldEntities);
}
// 更新调试管理器(基于FPS的数据发送)
diff --git a/packages/core/src/ECS/World.ts b/packages/core/src/ECS/World.ts
new file mode 100644
index 00000000..15f03796
--- /dev/null
+++ b/packages/core/src/ECS/World.ts
@@ -0,0 +1,504 @@
+import { IScene } from './IScene';
+import { Scene } from './Scene';
+import { createLogger } from '../Utils/Logger';
+
+const logger = createLogger('World');
+
+/**
+ * 全局系统接口
+ * 全局系统是在World级别运行的系统,不依赖特定Scene
+ */
+export interface IGlobalSystem {
+ /**
+ * 系统名称
+ */
+ readonly name: string;
+
+ /**
+ * 初始化系统
+ */
+ initialize?(): void;
+
+ /**
+ * 更新系统
+ */
+ update(deltaTime?: number): void;
+
+ /**
+ * 重置系统
+ */
+ reset?(): void;
+
+ /**
+ * 销毁系统
+ */
+ destroy?(): void;
+}
+
+/**
+ * World配置接口
+ */
+export interface IWorldConfig {
+ /**
+ * World名称
+ */
+ name?: string;
+
+ /**
+ * 是否启用调试模式
+ */
+ debug?: boolean;
+
+ /**
+ * 最大Scene数量限制
+ */
+ maxScenes?: number;
+
+ /**
+ * 是否自动清理空Scene
+ */
+ autoCleanup?: boolean;
+}
+
+/**
+ * World类 - ECS世界管理器
+ *
+ * World是Scene的容器,每个World可以管理多个Scene。
+ * 这种设计允许创建独立的游戏世界,如:
+ * - 游戏房间(每个房间一个World)
+ * - 不同的游戏模式
+ * - 独立的模拟环境
+ *
+ * @example
+ * ```typescript
+ * // 创建游戏房间的World
+ * const roomWorld = new World({ name: 'Room_001' });
+ *
+ * // 在World中创建Scene
+ * const gameScene = roomWorld.createScene('game', new Scene());
+ * const uiScene = roomWorld.createScene('ui', new Scene());
+ *
+ * // 更新整个World
+ * roomWorld.update(deltaTime);
+ * ```
+ */
+export class World {
+ public readonly name: string;
+ private readonly _config: IWorldConfig;
+ private readonly _scenes: Map = new Map();
+ private readonly _activeScenes: Set = new Set();
+ private readonly _globalSystems: IGlobalSystem[] = [];
+ private _isActive: boolean = false;
+ private _createdAt: number;
+
+ constructor(config: IWorldConfig = {}) {
+ this._config = {
+ name: 'World',
+ debug: false,
+ maxScenes: 10,
+ autoCleanup: true,
+ ...config
+ };
+
+ this.name = this._config.name!;
+ this._createdAt = Date.now();
+
+ logger.info(`创建World: ${this.name}`);
+ }
+
+ // ===== Scene管理 =====
+
+ /**
+ * 创建并添加Scene到World
+ */
+ public createScene(sceneId: string, sceneInstance?: T): T {
+ if (this._scenes.has(sceneId)) {
+ throw new Error(`Scene ID '${sceneId}' 已存在于World '${this.name}' 中`);
+ }
+
+ if (this._scenes.size >= this._config.maxScenes!) {
+ throw new Error(`World '${this.name}' 已达到最大Scene数量限制: ${this._config.maxScenes}`);
+ }
+
+ // 如果没有提供Scene实例,创建默认Scene
+ const scene = sceneInstance || (new Scene() as unknown as T);
+
+ // 设置Scene的标识
+ if ('id' in scene) {
+ (scene as any).id = sceneId;
+ }
+ if ('name' in scene && !scene.name) {
+ scene.name = sceneId;
+ }
+
+ this._scenes.set(sceneId, scene);
+
+ // 初始化Scene
+ scene.initialize();
+
+ logger.info(`在World '${this.name}' 中创建Scene: ${sceneId}`);
+ return scene;
+ }
+
+ /**
+ * 移除Scene
+ */
+ public removeScene(sceneId: string): boolean {
+ const scene = this._scenes.get(sceneId);
+ if (!scene) {
+ return false;
+ }
+
+ // 如果Scene正在运行,先停止它
+ if (this._activeScenes.has(sceneId)) {
+ this.setSceneActive(sceneId, false);
+ }
+
+ // 清理Scene资源
+ scene.end();
+ this._scenes.delete(sceneId);
+
+ logger.info(`从World '${this.name}' 中移除Scene: ${sceneId}`);
+ return true;
+ }
+
+ /**
+ * 获取Scene
+ */
+ public getScene(sceneId: string): T | null {
+ return this._scenes.get(sceneId) as T || null;
+ }
+
+ /**
+ * 获取所有Scene ID
+ */
+ public getSceneIds(): string[] {
+ return Array.from(this._scenes.keys());
+ }
+
+ /**
+ * 获取所有Scene
+ */
+ public getAllScenes(): IScene[] {
+ return Array.from(this._scenes.values());
+ }
+
+ /**
+ * 设置Scene激活状态
+ */
+ public setSceneActive(sceneId: string, active: boolean): void {
+ const scene = this._scenes.get(sceneId);
+ if (!scene) {
+ logger.warn(`Scene '${sceneId}' 不存在于World '${this.name}' 中`);
+ return;
+ }
+
+ if (active) {
+ this._activeScenes.add(sceneId);
+ // 启动Scene
+ if (scene.begin) {
+ scene.begin();
+ }
+ logger.debug(`在World '${this.name}' 中激活Scene: ${sceneId}`);
+ } else {
+ this._activeScenes.delete(sceneId);
+ // 可选择性地停止Scene,或者让它继续运行但不更新
+ logger.debug(`在World '${this.name}' 中停用Scene: ${sceneId}`);
+ }
+ }
+
+ /**
+ * 检查Scene是否激活
+ */
+ public isSceneActive(sceneId: string): boolean {
+ return this._activeScenes.has(sceneId);
+ }
+
+ /**
+ * 获取活跃Scene数量
+ */
+ public getActiveSceneCount(): number {
+ return this._activeScenes.size;
+ }
+
+ // ===== 全局System管理 =====
+
+ /**
+ * 添加全局System
+ * 全局System会在所有激活Scene之前更新
+ */
+ public addGlobalSystem(system: T): T {
+ if (this._globalSystems.includes(system)) {
+ return system;
+ }
+
+ this._globalSystems.push(system);
+ if (system.initialize) {
+ system.initialize();
+ }
+
+ logger.debug(`在World '${this.name}' 中添加全局System: ${system.name}`);
+ return system;
+ }
+
+ /**
+ * 移除全局System
+ */
+ public removeGlobalSystem(system: IGlobalSystem): boolean {
+ const index = this._globalSystems.indexOf(system);
+ if (index === -1) {
+ return false;
+ }
+
+ this._globalSystems.splice(index, 1);
+ if (system.reset) {
+ system.reset();
+ }
+
+ logger.debug(`从World '${this.name}' 中移除全局System: ${system.name}`);
+ return true;
+ }
+
+ /**
+ * 获取全局System
+ */
+ public getGlobalSystem(type: new (...args: any[]) => T): T | null {
+ for (const system of this._globalSystems) {
+ if (system instanceof type) {
+ return system as T;
+ }
+ }
+ return null;
+ }
+
+ // ===== World生命周期 =====
+
+ /**
+ * 启动World
+ */
+ public start(): void {
+ if (this._isActive) {
+ return;
+ }
+
+ this._isActive = true;
+
+ // 启动所有全局System
+ for (const system of this._globalSystems) {
+ if (system.initialize) {
+ system.initialize();
+ }
+ }
+
+ logger.info(`启动World: ${this.name}`);
+ }
+
+ /**
+ * 停止World
+ */
+ public stop(): void {
+ if (!this._isActive) {
+ return;
+ }
+
+ // 停止所有Scene
+ for (const sceneId of this._activeScenes) {
+ this.setSceneActive(sceneId, false);
+ }
+
+ // 重置所有全局System
+ for (const system of this._globalSystems) {
+ if (system.reset) {
+ system.reset();
+ }
+ }
+
+ this._isActive = false;
+ logger.info(`停止World: ${this.name}`);
+ }
+
+ /**
+ * 更新World中的全局System
+ * 注意:此方法由Core.update()调用,不应直接调用
+ */
+ public updateGlobalSystems(): void {
+ if (!this._isActive) {
+ return;
+ }
+
+ // 更新全局System
+ for (const system of this._globalSystems) {
+ if (system.update) {
+ system.update();
+ }
+ }
+ }
+
+ /**
+ * 更新World中的所有激活Scene
+ * 注意:此方法由Core.update()调用,不应直接调用
+ */
+ public updateScenes(): void {
+ if (!this._isActive) {
+ return;
+ }
+
+ // 更新所有激活的Scene
+ for (const sceneId of this._activeScenes) {
+ const scene = this._scenes.get(sceneId);
+ if (scene && scene.update) {
+ scene.update();
+ }
+ }
+
+ // 自动清理(如果启用)
+ if (this._config.autoCleanup && this.shouldAutoCleanup()) {
+ this.cleanup();
+ }
+ }
+
+ /**
+ * 销毁World
+ */
+ public destroy(): void {
+ logger.info(`销毁World: ${this.name}`);
+
+ // 停止World
+ this.stop();
+
+ // 销毁所有Scene
+ const sceneIds = Array.from(this._scenes.keys());
+ for (const sceneId of sceneIds) {
+ this.removeScene(sceneId);
+ }
+
+ // 清理全局System
+ for (const system of this._globalSystems) {
+ if (system.destroy) {
+ system.destroy();
+ } else if (system.reset) {
+ system.reset();
+ }
+ }
+ this._globalSystems.length = 0;
+
+ this._scenes.clear();
+ this._activeScenes.clear();
+ }
+
+ // ===== 状态信息 =====
+
+ /**
+ * 获取World状态
+ */
+ public getStatus() {
+ return {
+ name: this.name,
+ isActive: this._isActive,
+ sceneCount: this._scenes.size,
+ activeSceneCount: this._activeScenes.size,
+ globalSystemCount: this._globalSystems.length,
+ createdAt: this._createdAt,
+ config: { ...this._config },
+ scenes: Array.from(this._scenes.keys()).map(sceneId => ({
+ id: sceneId,
+ isActive: this._activeScenes.has(sceneId),
+ name: this._scenes.get(sceneId)?.name || sceneId
+ }))
+ };
+ }
+
+ /**
+ * 获取World统计信息
+ */
+ public getStats() {
+ const stats = {
+ totalEntities: 0,
+ totalSystems: this._globalSystems.length,
+ memoryUsage: 0,
+ performance: {
+ averageUpdateTime: 0,
+ maxUpdateTime: 0
+ }
+ };
+
+ // 统计所有Scene的实体数量
+ for (const scene of this._scenes.values()) {
+ if (scene.entities) {
+ stats.totalEntities += scene.entities.count;
+ }
+ if (scene.systems) {
+ stats.totalSystems += scene.systems.length;
+ }
+ }
+
+ return stats;
+ }
+
+ // ===== 私有方法 =====
+
+ /**
+ * 检查是否应该执行自动清理
+ */
+ private shouldAutoCleanup(): boolean {
+ // 简单的清理策略:如果有空Scene且超过5分钟没有实体
+ const currentTime = Date.now();
+ const cleanupThreshold = 5 * 60 * 1000; // 5分钟
+
+ for (const [sceneId, scene] of this._scenes) {
+ if (!this._activeScenes.has(sceneId) &&
+ scene.entities &&
+ scene.entities.count === 0 &&
+ (currentTime - this._createdAt) > cleanupThreshold) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * 执行清理操作
+ */
+ private cleanup(): void {
+ const sceneIds = Array.from(this._scenes.keys());
+ const currentTime = Date.now();
+ const cleanupThreshold = 5 * 60 * 1000; // 5分钟
+
+ for (const sceneId of sceneIds) {
+ const scene = this._scenes.get(sceneId);
+ if (scene &&
+ !this._activeScenes.has(sceneId) &&
+ scene.entities &&
+ scene.entities.count === 0 &&
+ (currentTime - this._createdAt) > cleanupThreshold) {
+
+ this.removeScene(sceneId);
+ logger.debug(`自动清理空Scene: ${sceneId} from World ${this.name}`);
+ }
+ }
+ }
+
+ // ===== 访问器 =====
+
+ /**
+ * 检查World是否激活
+ */
+ public get isActive(): boolean {
+ return this._isActive;
+ }
+
+ /**
+ * 获取Scene数量
+ */
+ public get sceneCount(): number {
+ return this._scenes.size;
+ }
+
+ /**
+ * 获取创建时间
+ */
+ public get createdAt(): number {
+ return this._createdAt;
+ }
+}
\ No newline at end of file
diff --git a/packages/core/src/ECS/WorldManager.ts b/packages/core/src/ECS/WorldManager.ts
new file mode 100644
index 00000000..354dba83
--- /dev/null
+++ b/packages/core/src/ECS/WorldManager.ts
@@ -0,0 +1,463 @@
+import { World, IWorldConfig } from './World';
+import { createLogger } from '../Utils/Logger';
+
+const logger = createLogger('WorldManager');
+
+/**
+ * WorldManager配置接口
+ */
+export interface IWorldManagerConfig {
+ /**
+ * 最大World数量
+ */
+ maxWorlds?: number;
+
+ /**
+ * 是否自动清理空World
+ */
+ autoCleanup?: boolean;
+
+ /**
+ * 清理间隔(毫秒)
+ */
+ cleanupInterval?: number;
+
+ /**
+ * 是否启用调试模式
+ */
+ debug?: boolean;
+}
+
+/**
+ * World管理器 - 管理所有World实例
+ *
+ * WorldManager是全局单例,负责管理所有World的生命周期。
+ * 每个World都是独立的ECS环境,可以包含多个Scene。
+ *
+ * 设计理念:
+ * - Core负责单Scene的传统ECS管理
+ * - World负责多Scene的管理和协调
+ * - WorldManager负责多World的全局管理
+ *
+ * @example
+ * ```typescript
+ * // 获取全局WorldManager
+ * const worldManager = WorldManager.getInstance();
+ *
+ * // 创建游戏房间World
+ * const roomWorld = worldManager.createWorld('room_001', {
+ * name: 'GameRoom_001',
+ * maxScenes: 5
+ * });
+ *
+ * // 在游戏循环中更新所有World
+ * worldManager.updateAll(deltaTime);
+ * ```
+ */
+export class WorldManager {
+ private static _instance: WorldManager | null = null;
+
+ private readonly _config: IWorldManagerConfig;
+ private readonly _worlds: Map = new Map();
+ private readonly _activeWorlds: Set = new Set();
+ private _cleanupTimer: NodeJS.Timeout | null = null;
+ private _isRunning: boolean = false;
+
+ private constructor(config: IWorldManagerConfig = {}) {
+ this._config = {
+ maxWorlds: 50,
+ autoCleanup: true,
+ cleanupInterval: 30000, // 30秒
+ debug: false,
+ ...config
+ };
+
+ logger.info('WorldManager已初始化', {
+ maxWorlds: this._config.maxWorlds,
+ autoCleanup: this._config.autoCleanup,
+ cleanupInterval: this._config.cleanupInterval
+ });
+
+ this.startCleanupTimer();
+ }
+
+ /**
+ * 获取WorldManager单例实例
+ */
+ public static getInstance(config?: IWorldManagerConfig): WorldManager {
+ if (!this._instance) {
+ this._instance = new WorldManager(config);
+ }
+ return this._instance;
+ }
+
+ /**
+ * 重置WorldManager实例(主要用于测试)
+ */
+ public static reset(): void {
+ if (this._instance) {
+ this._instance.destroy();
+ this._instance = null;
+ }
+ }
+
+ // ===== World管理 =====
+
+ /**
+ * 创建新World
+ */
+ public createWorld(worldId: string, config?: IWorldConfig): World {
+ if (!worldId || typeof worldId !== 'string' || worldId.trim() === '') {
+ throw new Error('World ID不能为空');
+ }
+
+ if (this._worlds.has(worldId)) {
+ throw new Error(`World ID '${worldId}' 已存在`);
+ }
+
+ if (this._worlds.size >= this._config.maxWorlds!) {
+ throw new Error(`已达到最大World数量限制: ${this._config.maxWorlds}`);
+ }
+
+ const worldConfig: IWorldConfig = {
+ name: worldId,
+ debug: this._config.debug,
+ ...config
+ };
+
+ const world = new World(worldConfig);
+ this._worlds.set(worldId, world);
+
+ logger.info(`创建World: ${worldId}`, { config: worldConfig });
+ return world;
+ }
+
+ /**
+ * 移除World
+ */
+ public removeWorld(worldId: string): boolean {
+ const world = this._worlds.get(worldId);
+ if (!world) {
+ return false;
+ }
+
+ // 如果World正在运行,先停止它
+ if (this._activeWorlds.has(worldId)) {
+ this.setWorldActive(worldId, false);
+ }
+
+ // 销毁World
+ world.destroy();
+ this._worlds.delete(worldId);
+
+ logger.info(`移除World: ${worldId}`);
+ return true;
+ }
+
+ /**
+ * 获取World
+ */
+ public getWorld(worldId: string): World | null {
+ return this._worlds.get(worldId) || null;
+ }
+
+ /**
+ * 获取所有World ID
+ */
+ public getWorldIds(): string[] {
+ return Array.from(this._worlds.keys());
+ }
+
+ /**
+ * 获取所有World
+ */
+ public getAllWorlds(): World[] {
+ return Array.from(this._worlds.values());
+ }
+
+ /**
+ * 设置World激活状态
+ */
+ public setWorldActive(worldId: string, active: boolean): void {
+ const world = this._worlds.get(worldId);
+ if (!world) {
+ logger.warn(`World '${worldId}' 不存在`);
+ return;
+ }
+
+ if (active) {
+ this._activeWorlds.add(worldId);
+ world.start();
+ logger.debug(`激活World: ${worldId}`);
+ } else {
+ this._activeWorlds.delete(worldId);
+ world.stop();
+ logger.debug(`停用World: ${worldId}`);
+ }
+ }
+
+ /**
+ * 检查World是否激活
+ */
+ public isWorldActive(worldId: string): boolean {
+ return this._activeWorlds.has(worldId);
+ }
+
+ // ===== 批量操作 =====
+
+ /**
+ * 获取所有激活的World
+ * 注意:此方法供Core.update()使用
+ */
+ public getActiveWorlds(): World[] {
+ const activeWorlds: World[] = [];
+ for (const worldId of this._activeWorlds) {
+ const world = this._worlds.get(worldId);
+ if (world) {
+ activeWorlds.push(world);
+ }
+ }
+ return activeWorlds;
+ }
+
+ /**
+ * 启动所有World
+ */
+ public startAll(): void {
+ this._isRunning = true;
+
+ for (const worldId of this._worlds.keys()) {
+ this.setWorldActive(worldId, true);
+ }
+
+ logger.info('启动所有World');
+ }
+
+ /**
+ * 停止所有World
+ */
+ public stopAll(): void {
+ this._isRunning = false;
+
+ for (const worldId of this._activeWorlds) {
+ this.setWorldActive(worldId, false);
+ }
+
+ logger.info('停止所有World');
+ }
+
+ /**
+ * 查找满足条件的World
+ */
+ public findWorlds(predicate: (world: World) => boolean): World[] {
+ const results: World[] = [];
+ for (const world of this._worlds.values()) {
+ if (predicate(world)) {
+ results.push(world);
+ }
+ }
+ return results;
+ }
+
+ /**
+ * 根据名称查找World
+ */
+ public findWorldByName(name: string): World | null {
+ for (const world of this._worlds.values()) {
+ if (world.name === name) {
+ return world;
+ }
+ }
+ return null;
+ }
+
+ // ===== 统计和监控 =====
+
+ /**
+ * 获取WorldManager统计信息
+ */
+ public getStats() {
+ const stats = {
+ totalWorlds: this._worlds.size,
+ activeWorlds: this._activeWorlds.size,
+ totalScenes: 0,
+ totalEntities: 0,
+ totalSystems: 0,
+ memoryUsage: 0,
+ isRunning: this._isRunning,
+ config: { ...this._config },
+ worlds: [] as any[]
+ };
+
+ for (const [worldId, world] of this._worlds) {
+ const worldStats = world.getStats();
+ stats.totalScenes += worldStats.totalSystems; // World的getStats可能需要调整
+ stats.totalEntities += worldStats.totalEntities;
+ stats.totalSystems += worldStats.totalSystems;
+
+ stats.worlds.push({
+ id: worldId,
+ name: world.name,
+ isActive: this._activeWorlds.has(worldId),
+ sceneCount: world.sceneCount,
+ ...worldStats
+ });
+ }
+
+ return stats;
+ }
+
+ /**
+ * 获取详细状态信息
+ */
+ public getDetailedStatus() {
+ return {
+ ...this.getStats(),
+ worlds: Array.from(this._worlds.entries()).map(([worldId, world]) => ({
+ id: worldId,
+ isActive: this._activeWorlds.has(worldId),
+ status: world.getStatus()
+ }))
+ };
+ }
+
+ // ===== 生命周期管理 =====
+
+ /**
+ * 清理空World
+ */
+ public cleanup(): number {
+ const worldsToRemove: string[] = [];
+
+ for (const [worldId, world] of this._worlds) {
+ if (this.shouldCleanupWorld(world)) {
+ worldsToRemove.push(worldId);
+ }
+ }
+
+ for (const worldId of worldsToRemove) {
+ this.removeWorld(worldId);
+ }
+
+ if (worldsToRemove.length > 0) {
+ logger.debug(`清理了 ${worldsToRemove.length} 个World`);
+ }
+
+ return worldsToRemove.length;
+ }
+
+ /**
+ * 销毁WorldManager
+ */
+ public destroy(): void {
+ logger.info('正在销毁WorldManager...');
+
+ // 停止清理定时器
+ this.stopCleanupTimer();
+
+ // 停止所有World
+ this.stopAll();
+
+ // 销毁所有World
+ const worldIds = Array.from(this._worlds.keys());
+ for (const worldId of worldIds) {
+ this.removeWorld(worldId);
+ }
+
+ this._worlds.clear();
+ this._activeWorlds.clear();
+ this._isRunning = false;
+
+ logger.info('WorldManager已销毁');
+ }
+
+ // ===== 私有方法 =====
+
+ /**
+ * 启动清理定时器
+ */
+ private startCleanupTimer(): void {
+ if (!this._config.autoCleanup || this._cleanupTimer) {
+ return;
+ }
+
+ this._cleanupTimer = setInterval(() => {
+ this.cleanup();
+ }, this._config.cleanupInterval);
+
+ logger.debug(`启动World清理定时器,间隔: ${this._config.cleanupInterval}ms`);
+ }
+
+ /**
+ * 停止清理定时器
+ */
+ private stopCleanupTimer(): void {
+ if (this._cleanupTimer) {
+ clearInterval(this._cleanupTimer);
+ this._cleanupTimer = null;
+ logger.debug('停止World清理定时器');
+ }
+ }
+
+ /**
+ * 判断World是否应该被清理
+ */
+ private shouldCleanupWorld(world: World): boolean {
+ // 清理策略:
+ // 1. World未激活
+ // 2. 没有Scene或所有Scene都是空的
+ // 3. 创建时间超过10分钟
+
+ if (world.isActive) {
+ return false;
+ }
+
+ if (world.sceneCount === 0) {
+ const age = Date.now() - world.createdAt;
+ return age > 10 * 60 * 1000; // 10分钟
+ }
+
+ // 检查是否所有Scene都是空的
+ const allScenes = world.getAllScenes();
+ const hasEntities = allScenes.some(scene =>
+ scene.entities && scene.entities.count > 0
+ );
+
+ if (!hasEntities) {
+ const age = Date.now() - world.createdAt;
+ return age > 10 * 60 * 1000; // 10分钟
+ }
+
+ return false;
+ }
+
+ // ===== 访问器 =====
+
+ /**
+ * 获取World总数
+ */
+ public get worldCount(): number {
+ return this._worlds.size;
+ }
+
+ /**
+ * 获取激活World数量
+ */
+ public get activeWorldCount(): number {
+ return this._activeWorlds.size;
+ }
+
+ /**
+ * 检查是否正在运行
+ */
+ public get isRunning(): boolean {
+ return this._isRunning;
+ }
+
+ /**
+ * 获取配置
+ */
+ public get config(): IWorldManagerConfig {
+ return { ...this._config };
+ }
+}
\ No newline at end of file
diff --git a/packages/core/src/ECS/index.ts b/packages/core/src/ECS/index.ts
index 2f20612d..d40ae819 100644
--- a/packages/core/src/ECS/index.ts
+++ b/packages/core/src/ECS/index.ts
@@ -6,6 +6,8 @@ export * from './Utils';
export * from './Decorators';
export { Scene } from './Scene';
export { IScene, ISceneFactory, ISceneConfig } from './IScene';
+export { World, IWorldConfig } from './World';
+export { WorldManager, IWorldManagerConfig } from './WorldManager';
export { EntityManager, EntityQueryBuilder } from './Core/EntityManager';
export * from './Core/Events';
export * from './Core/Query';
diff --git a/packages/core/tests/ECS/Core/WorldCoreIntegration.test.ts b/packages/core/tests/ECS/Core/WorldCoreIntegration.test.ts
new file mode 100644
index 00000000..797d3b55
--- /dev/null
+++ b/packages/core/tests/ECS/Core/WorldCoreIntegration.test.ts
@@ -0,0 +1,589 @@
+import { Core } from '../../../src/Core';
+import { Scene } from '../../../src/ECS/Scene';
+import { World, IGlobalSystem } from '../../../src/ECS/World';
+import { WorldManager } from '../../../src/ECS/WorldManager';
+import { EntitySystem } from '../../../src/ECS/Systems/EntitySystem';
+import { Component } from '../../../src/ECS/Component';
+import { Matcher } from '../../../src/ECS/Utils/Matcher';
+import { Entity } from '../../../src/ECS/Entity';
+
+// 测试用组件
+class TestComponent extends Component {
+ public value: number = 0;
+
+ constructor(value: number = 0) {
+ super();
+ this.value = value;
+ }
+
+ public reset(): void {
+ this.value = 0;
+ }
+}
+
+class NetworkComponent extends Component {
+ public playerId: string;
+
+ constructor(playerId: string) {
+ super();
+ this.playerId = playerId;
+ }
+
+ public reset(): void {
+ this.playerId = '';
+ }
+}
+
+// 测试用系统
+class TestGlobalSystem extends EntitySystem {
+ public processedEntities: Entity[] = [];
+ public updateCount: number = 0;
+
+ constructor() {
+ super(Matcher.empty().all(TestComponent));
+ }
+
+ protected override process(entities: Entity[]): void {
+ this.processedEntities = [...entities];
+ this.updateCount++;
+ }
+}
+
+// 正确的全局系统实现
+class NetworkSyncGlobalSystem implements IGlobalSystem {
+ public readonly name = 'NetworkSyncSystem';
+ public updateCount: number = 0;
+
+ public initialize(): void {
+ // 初始化网络连接等
+ }
+
+ public update(): void {
+ this.updateCount++;
+ // 同步网络数据等全局逻辑
+ }
+
+ public reset(): void {
+ this.updateCount = 0;
+ }
+
+ public destroy(): void {
+ // 清理网络连接等
+ }
+}
+
+// Scene级别的EntitySystem(正确的用法)
+class NetworkSyncSystem extends EntitySystem {
+ public syncCount: number = 0;
+
+ constructor() {
+ super(Matcher.empty().all(NetworkComponent));
+ }
+
+ protected override process(entities: Entity[]): void {
+ this.syncCount++;
+ }
+}
+
+// World级别的网络同步全局系统
+class NetworkGlobalSystem implements IGlobalSystem {
+ public readonly name = 'NetworkGlobalSystem';
+ public syncCount: number = 0;
+
+ public initialize(): void {
+ // 初始化网络连接
+ }
+
+ public update(): void {
+ this.syncCount++;
+ // 全局网络同步逻辑
+ }
+
+ public reset(): void {
+ this.syncCount = 0;
+ }
+
+ public destroy(): void {
+ // 清理网络连接
+ }
+}
+
+// 测试用Scene
+class TestScene extends Scene {
+ public updateCallCount: number = 0;
+
+ public override update(): void {
+ super.update();
+ this.updateCallCount++;
+ }
+}
+
+describe('World与Core集成测试', () => {
+ beforeEach(() => {
+ // 重置Core和WorldManager
+ if ((Core as any)._instance) {
+ (Core as any)._instance = null;
+ }
+ WorldManager['_instance'] = null;
+ });
+
+ afterEach(() => {
+ // 清理资源
+ if ((Core as any)._instance) {
+ const worldManager = Core.getWorldManager?.();
+ if (worldManager) {
+ const worldIds = worldManager.getWorldIds();
+ worldIds.forEach(id => {
+ worldManager.removeWorld(id);
+ });
+ }
+ (Core as any)._instance = null;
+ }
+ WorldManager['_instance'] = null;
+ });
+
+ describe('融合设计基础功能', () => {
+ test('单Scene模式应该保持向后兼容', () => {
+ Core.create({ debug: false });
+
+ // 传统单Scene用法
+ const scene = new Scene();
+ scene.name = 'TestScene';
+
+ Core.setScene(scene);
+
+ const retrievedScene = Core.getScene();
+ expect(retrievedScene).toBe(scene);
+ expect(retrievedScene?.name).toBe('TestScene');
+ });
+
+ test('启用WorldManager后应该支持多World功能', () => {
+ Core.create({ debug: false });
+ Core.enableWorldManager();
+
+ const worldManager = Core.getWorldManager();
+ expect(worldManager).toBeDefined();
+
+ const world = worldManager.createWorld('TestWorld');
+ expect(world).toBeDefined();
+ expect(world.name).toBe('TestWorld');
+ });
+
+ test('getWorldManager应该自动创建WorldManager', () => {
+ Core.create({ debug: false });
+
+ // 获取WorldManager会自动创建实例
+ const worldManager = Core.getWorldManager();
+ expect(worldManager).toBeDefined();
+
+ // 多次获取应该返回同一个实例
+ const worldManager2 = Core.getWorldManager();
+ expect(worldManager2).toBe(worldManager);
+ });
+
+ test('单Scene模式下Core.update应该正常工作', () => {
+ Core.create({ debug: false });
+
+ const scene = new TestScene();
+ Core.setScene(scene);
+
+ // 模拟更新
+ Core.update(0.016);
+
+ expect(scene.updateCallCount).toBeGreaterThan(0);
+ });
+ });
+
+ describe('默认World机制', () => {
+ test('设置Scene应该自动创建默认World', () => {
+ Core.create({ debug: false });
+
+ const scene = new Scene();
+ Core.setScene(scene);
+
+ // 启用WorldManager后应该能看到默认World
+ Core.enableWorldManager();
+ const worldManager = Core.getWorldManager();
+
+ expect(worldManager.getWorld('__default__')).toBeDefined();
+
+ const defaultWorld = worldManager.getWorld('__default__');
+ expect(defaultWorld).toBeDefined();
+ expect(defaultWorld?.getScene('__main__')).toBe(scene);
+ });
+
+ test('默认World的Scene应该正确激活', () => {
+ Core.create({ debug: false });
+
+ const scene = new Scene();
+ Core.setScene(scene);
+
+ Core.enableWorldManager();
+ const worldManager = Core.getWorldManager();
+ const defaultWorld = worldManager.getWorld('__default__');
+
+ expect(defaultWorld?.isSceneActive('__main__')).toBe(true);
+ });
+
+ test('替换默认Scene应该正确处理', () => {
+ Core.create({ debug: false });
+
+ const scene1 = new Scene();
+ scene1.name = 'Scene1';
+ Core.setScene(scene1);
+
+ const scene2 = new Scene();
+ scene2.name = 'Scene2';
+ Core.setScene(scene2);
+
+ const currentScene = Core.getScene();
+ expect(currentScene).toBe(scene2);
+ expect(currentScene?.name).toBe('Scene2');
+ });
+ });
+
+ describe('多World更新机制', () => {
+ test('Core.update应该更新所有活跃World', () => {
+ Core.create({ debug: false });
+ Core.enableWorldManager();
+
+ const worldManager = Core.getWorldManager();
+
+ // 创建多个World
+ const world1 = worldManager.createWorld('World1');
+ const world2 = worldManager.createWorld('World2');
+ const world3 = worldManager.createWorld('World3');
+
+ // 为每个World创建Scene和System
+ const scene1 = world1.createScene('scene1', new TestScene());
+ const scene2 = world2.createScene('scene2', new TestScene());
+ const scene3 = world3.createScene('scene3', new TestScene());
+
+ // 启动部分World
+ worldManager.setWorldActive('World1', true);
+ worldManager.setWorldActive('World2', true);
+ // world3保持未启动
+
+ world1.setSceneActive('scene1', true);
+ world2.setSceneActive('scene2', true);
+
+ // 执行更新
+ Core.update(0.016);
+
+ // 检查只有激活的World被更新
+ expect(scene1.updateCallCount).toBeGreaterThan(0);
+ expect(scene2.updateCallCount).toBeGreaterThan(0);
+ expect(scene3.updateCallCount).toBe(0);
+ });
+
+ test('全局系统应该在Scene更新前执行', () => {
+ Core.create({ debug: false });
+ Core.enableWorldManager();
+
+ const worldManager = Core.getWorldManager();
+ const world = worldManager.createWorld('TestWorld');
+
+ // 添加正确设计的全局系统(业务逻辑系统,不是EntitySystem)
+ const globalSystem = new NetworkSyncGlobalSystem();
+ world.addGlobalSystem(globalSystem);
+
+ // 创建Scene
+ const scene = world.createScene('testScene');
+
+ worldManager.setWorldActive('TestWorld', true);
+ world.setSceneActive('testScene', true);
+
+ // 执行更新
+ Core.update(0.016);
+
+ // 验证全局System被正确更新
+ expect(globalSystem.updateCount).toBeGreaterThan(0);
+ });
+ });
+
+ describe('多房间游戏服务器场景', () => {
+ test('多个游戏房间应该独立运行', () => {
+ Core.create({ debug: false });
+ Core.enableWorldManager();
+
+ const worldManager = Core.getWorldManager();
+
+ // 创建两个游戏房间
+ const room1 = worldManager.createWorld('Room_001');
+ const room2 = worldManager.createWorld('Room_002');
+
+ // 为每个房间设置Scene
+ const gameScene1 = room1.createScene('game');
+ const gameScene2 = room2.createScene('game');
+
+ // 为每个房间添加全局网络系统
+ const netSystem1 = new NetworkGlobalSystem();
+ const netSystem2 = new NetworkGlobalSystem();
+
+ room1.addGlobalSystem(netSystem1);
+ room2.addGlobalSystem(netSystem2);
+
+ // 在每个房间创建玩家
+ const player1 = gameScene1.createEntity('Player1');
+ player1.addComponent(new NetworkComponent('player_123'));
+
+ const player2 = gameScene2.createEntity('Player2');
+ player2.addComponent(new NetworkComponent('player_456'));
+
+ // 启动房间
+ worldManager.setWorldActive('Room_001', true);
+ worldManager.setWorldActive('Room_002', true);
+ room1.setSceneActive('game', true);
+ room2.setSceneActive('game', true);
+
+ // 模拟游戏循环
+ for (let i = 0; i < 5; i++) {
+ Core.update(0.016);
+ }
+
+ // 验证每个房间独立运行
+ expect(netSystem1.syncCount).toBeGreaterThan(0);
+ expect(netSystem2.syncCount).toBeGreaterThan(0);
+ expect(room1.getActiveSceneCount()).toBe(1);
+ expect(room2.getActiveSceneCount()).toBe(1);
+ });
+
+ test('房间销毁应该完全清理资源', () => {
+ Core.create({ debug: false });
+ Core.enableWorldManager();
+
+ const worldManager = Core.getWorldManager();
+
+ // 创建房间
+ const room = worldManager.createWorld('TempRoom');
+ const scene = room.createScene('game');
+
+ // 添加内容
+ for (let i = 0; i < 10; i++) {
+ const entity = scene.createEntity(`Entity${i}`);
+ entity.addComponent(new TestComponent(i));
+ }
+
+ room.addGlobalSystem(new NetworkSyncGlobalSystem());
+ worldManager.setWorldActive('TempRoom', true);
+ room.setSceneActive('game', true);
+
+ // 验证房间正常运行
+ Core.update(0.016);
+
+ const beforeDestroy = worldManager.getStats();
+ expect(beforeDestroy.totalWorlds).toBe(1);
+ expect(beforeDestroy.activeWorlds).toBe(1);
+
+ // 销毁房间
+ worldManager.removeWorld('TempRoom');
+
+ const afterDestroy = worldManager.getStats();
+ expect(afterDestroy.totalWorlds).toBe(0);
+ expect(afterDestroy.activeWorlds).toBe(0);
+ });
+ });
+
+ describe('客户端多层Scene架构', () => {
+ test('分层Scene应该同时运行', () => {
+ Core.create({ debug: false });
+ Core.enableWorldManager();
+
+ const worldManager = Core.getWorldManager();
+ const clientWorld = worldManager.createWorld('ClientWorld');
+
+ // 创建不同层的Scene
+ const gameplayScene = clientWorld.createScene('gameplay', new TestScene());
+ const uiScene = clientWorld.createScene('ui', new TestScene());
+ const effectsScene = clientWorld.createScene('effects', new TestScene());
+
+ // 启动世界并激活所有Scene
+ worldManager.setWorldActive('ClientWorld', true);
+ clientWorld.setSceneActive('gameplay', true);
+ clientWorld.setSceneActive('ui', true);
+ clientWorld.setSceneActive('effects', true);
+
+ // 执行更新
+ Core.update(0.016);
+
+ // 验证所有Scene都被更新
+ expect(gameplayScene.updateCallCount).toBeGreaterThan(0);
+ expect(uiScene.updateCallCount).toBeGreaterThan(0);
+ expect(effectsScene.updateCallCount).toBeGreaterThan(0);
+ });
+
+ test('Scene的动态激活和停用', () => {
+ Core.create({ debug: false });
+ Core.enableWorldManager();
+
+ const worldManager = Core.getWorldManager();
+ const world = worldManager.createWorld('DynamicWorld');
+
+ const gameScene = world.createScene('game', new TestScene());
+ const menuScene = world.createScene('menu', new TestScene());
+
+ worldManager.setWorldActive('DynamicWorld', true);
+
+ // 初始状态:只有游戏Scene激活
+ world.setSceneActive('game', true);
+ world.setSceneActive('menu', false);
+
+ Core.update(0.016);
+
+ const gameCount1 = gameScene.updateCallCount;
+ const menuCount1 = menuScene.updateCallCount;
+
+ // 切换到菜单
+ world.setSceneActive('game', false);
+ world.setSceneActive('menu', true);
+
+ Core.update(0.016);
+
+ const gameCount2 = gameScene.updateCallCount;
+ const menuCount2 = menuScene.updateCallCount;
+
+ // 验证Scene状态切换
+ expect(gameCount2).toBe(gameCount1); // 游戏Scene停止更新
+ expect(menuCount2).toBeGreaterThan(menuCount1); // 菜单Scene开始更新
+ });
+ });
+
+ describe('性能和稳定性', () => {
+ test('大量World和Scene应该稳定运行', () => {
+ Core.create({ debug: false });
+ Core.enableWorldManager();
+
+ const worldManager = Core.getWorldManager();
+ const worldCount = 20;
+ const scenePerWorld = 3;
+
+ // 创建大量World和Scene
+ for (let i = 0; i < worldCount; i++) {
+ const world = worldManager.createWorld(`World${i}`);
+
+ for (let j = 0; j < scenePerWorld; j++) {
+ const scene = world.createScene(`Scene${j}`, new TestScene());
+
+ // 添加一些实体
+ for (let k = 0; k < 5; k++) {
+ const entity = scene.createEntity(`Entity${k}`);
+ entity.addComponent(new TestComponent(k));
+ }
+
+ world.setSceneActive(`Scene${j}`, true);
+ }
+
+ worldManager.setWorldActive(`World${i}`, true);
+ }
+
+ // 验证所有资源创建成功
+ expect(worldManager.getWorldIds()).toHaveLength(worldCount);
+ expect(worldManager.getActiveWorlds()).toHaveLength(worldCount);
+
+ // 执行多次更新测试稳定性
+ for (let i = 0; i < 10; i++) {
+ expect(() => {
+ Core.update(0.016);
+ }).not.toThrow();
+ }
+
+ // 验证更新正常工作
+ const activeWorlds = worldManager.getActiveWorlds();
+ activeWorlds.forEach(world => {
+ const scenes = world.getAllScenes();
+ scenes.forEach(scene => {
+ if (scene instanceof TestScene && world.isSceneActive(scene.name)) {
+ expect(scene.updateCallCount).toBeGreaterThan(0);
+ }
+ });
+ });
+ });
+
+ test('频繁的World创建和销毁应该不影响性能', () => {
+ Core.create({ debug: false });
+ Core.enableWorldManager();
+
+ const worldManager = Core.getWorldManager();
+
+ // 频繁创建和销毁World
+ for (let cycle = 0; cycle < 10; cycle++) {
+ // 创建批次World
+ const worldIds: string[] = [];
+ for (let i = 0; i < 5; i++) {
+ const worldId = `Cycle${cycle}_World${i}`;
+ worldIds.push(worldId);
+
+ const world = worldManager.createWorld(worldId);
+ const scene = world.createScene('test');
+ scene.createEntity('entity');
+
+ worldManager.setWorldActive(worldId, true);
+ world.setSceneActive('test', true);
+ }
+
+ // 更新一次
+ Core.update(0.016);
+
+ // 销毁批次World
+ worldIds.forEach(id => {
+ worldManager.removeWorld(id);
+ });
+
+ // 验证清理完成
+ expect(worldManager.getWorldIds()).toHaveLength(0);
+ expect(worldManager.getActiveWorlds()).toHaveLength(0);
+ }
+ });
+ });
+
+ describe('错误处理和边界情况', () => {
+ test('Core未初始化时操作应该抛出合适错误', () => {
+ // getScene 会返回 null 而不是抛出错误
+ expect(Core.getScene()).toBeNull();
+
+ expect(() => {
+ Core.setScene(new Scene());
+ }).toThrow();
+ });
+
+ test('在World销毁后继续操作应该安全', () => {
+ Core.create({ debug: false });
+ Core.enableWorldManager();
+
+ const worldManager = Core.getWorldManager();
+ const world = worldManager.createWorld('DestroyTest');
+
+ worldManager.setWorldActive('DestroyTest', true);
+ worldManager.removeWorld('DestroyTest');
+
+ // 对已销毁的World进行操作应该不会崩溃
+ expect(() => {
+ world.updateGlobalSystems();
+ world.updateScenes();
+ }).not.toThrow();
+ });
+
+ test('混合使用单Scene和多World模式', () => {
+ Core.create({ debug: false });
+
+ // 直接启用WorldManager(避免先使用单Scene创建限制性配置)
+ const worldManager = Core.getWorldManager();
+
+ // 然后使用单Scene模式
+ const singleScene = new Scene();
+ Core.setScene(singleScene);
+
+ // 验证默认World被创建
+ expect(worldManager.getWorld('__default__')).toBeDefined();
+
+ // 创建额外的World
+ const extraWorld = worldManager.createWorld('ExtraWorld');
+ worldManager.setWorldActive('ExtraWorld', true);
+
+ // 两种模式应该能共存
+ expect(() => {
+ Core.update(0.016);
+ }).not.toThrow();
+ });
+ });
+});
\ No newline at end of file
diff --git a/packages/core/tests/ECS/World.test.ts b/packages/core/tests/ECS/World.test.ts
new file mode 100644
index 00000000..0dba9c56
--- /dev/null
+++ b/packages/core/tests/ECS/World.test.ts
@@ -0,0 +1,466 @@
+import { World, IWorldConfig, IGlobalSystem } from '../../src/ECS/World';
+import { Scene } from '../../src/ECS/Scene';
+import { EntitySystem } from '../../src/ECS/Systems/EntitySystem';
+import { Entity } from '../../src/ECS/Entity';
+import { Component } from '../../src/ECS/Component';
+import { Matcher } from '../../src/ECS/Utils/Matcher';
+
+// 测试用组件
+class TestComponent extends Component {
+ public value: number = 0;
+
+ constructor(value: number = 0) {
+ super();
+ this.value = value;
+ }
+}
+
+class PlayerComponent extends Component {
+ public playerId: string;
+
+ constructor(playerId: string) {
+ super();
+ this.playerId = playerId;
+ }
+}
+
+// 测试用全局系统
+class TestGlobalSystem implements IGlobalSystem {
+ public readonly name = 'TestGlobalSystem';
+ public updateCount: number = 0;
+
+ public initialize(): void {
+ // 初始化逻辑
+ }
+
+ public update(): void {
+ this.updateCount++;
+ }
+
+ public reset(): void {
+ this.updateCount = 0;
+ }
+
+ public destroy(): void {
+ // 销毁逻辑
+ }
+}
+
+class TestSceneSystem extends EntitySystem {
+ public updateCount = 0;
+
+ constructor() {
+ super(Matcher.empty().all(PlayerComponent));
+ }
+
+ protected override process(): void {
+ this.updateCount++;
+ }
+}
+
+// 测试用Scene
+class TestScene extends Scene {
+ public initializeCalled = false;
+ public beginCalled = false;
+ public endCalled = false;
+
+ public override initialize(): void {
+ this.initializeCalled = true;
+ super.initialize();
+ }
+
+ public override begin(): void {
+ this.beginCalled = true;
+ super.begin();
+ }
+
+ public override end(): void {
+ this.endCalled = true;
+ super.end();
+ }
+}
+
+describe('World', () => {
+ let world: World;
+
+ beforeEach(() => {
+ world = new World({ name: 'TestWorld' });
+ });
+
+ afterEach(() => {
+ if (world) {
+ world.destroy();
+ }
+ });
+
+ describe('基础功能', () => {
+ test('创建World时应该设置正确的配置', () => {
+ const config: IWorldConfig = {
+ name: 'GameWorld',
+ debug: true,
+ maxScenes: 5,
+ autoCleanup: false
+ };
+
+ const testWorld = new World(config);
+
+ expect(testWorld.name).toBe('GameWorld');
+ expect(testWorld.sceneCount).toBe(0);
+ expect(testWorld.isActive).toBe(false);
+ expect(testWorld.createdAt).toBeGreaterThan(0);
+
+ testWorld.destroy();
+ });
+
+ test('默认配置应该正确', () => {
+ const defaultWorld = new World();
+
+ expect(defaultWorld.name).toBe('World');
+ expect(defaultWorld.sceneCount).toBe(0);
+ expect(defaultWorld.isActive).toBe(false);
+
+ defaultWorld.destroy();
+ });
+ });
+
+ describe('Scene管理', () => {
+ test('创建Scene应该成功', () => {
+ const scene = world.createScene('test-scene');
+
+ expect(scene).toBeDefined();
+ expect(world.sceneCount).toBe(1);
+ expect(world.getSceneIds()).toContain('test-scene');
+ });
+
+ test('创建Scene时传入自定义Scene实例', () => {
+ const customScene = new TestScene();
+ const scene = world.createScene('custom-scene', customScene);
+
+ expect(scene).toBe(customScene);
+ expect(scene.initializeCalled).toBe(true);
+ expect(world.sceneCount).toBe(1);
+ });
+
+ test('重复的Scene ID应该抛出错误', () => {
+ world.createScene('duplicate');
+
+ expect(() => {
+ world.createScene('duplicate');
+ }).toThrow("Scene ID 'duplicate' 已存在于World 'TestWorld' 中");
+ });
+
+ test('超出最大Scene数量限制应该抛出错误', () => {
+ const limitedWorld = new World({ maxScenes: 2 });
+
+ limitedWorld.createScene('scene1');
+ limitedWorld.createScene('scene2');
+
+ expect(() => {
+ limitedWorld.createScene('scene3');
+ }).toThrow("World 'World' 已达到最大Scene数量限制: 2");
+
+ limitedWorld.destroy();
+ });
+
+ test('获取Scene应该正确', () => {
+ const scene = world.createScene('get-test');
+ const retrievedScene = world.getScene('get-test');
+
+ expect(retrievedScene).toBe(scene);
+ });
+
+ test('获取不存在的Scene应该返回null', () => {
+ const scene = world.getScene('non-existent');
+ expect(scene).toBeNull();
+ });
+
+ test('移除Scene应该正确清理', () => {
+ const testScene = new TestScene();
+ world.createScene('remove-test', testScene);
+ world.setSceneActive('remove-test', true);
+
+ const removed = world.removeScene('remove-test');
+
+ expect(removed).toBe(true);
+ expect(world.sceneCount).toBe(0);
+ expect(world.getScene('remove-test')).toBeNull();
+ expect(testScene.endCalled).toBe(true);
+ });
+
+ test('移除不存在的Scene应该返回false', () => {
+ const removed = world.removeScene('non-existent');
+ expect(removed).toBe(false);
+ });
+
+ test('获取所有Scene应该正确', () => {
+ const scene1 = world.createScene('scene1');
+ const scene2 = world.createScene('scene2');
+
+ const allScenes = world.getAllScenes();
+
+ expect(allScenes).toHaveLength(2);
+ expect(allScenes).toContain(scene1);
+ expect(allScenes).toContain(scene2);
+ });
+ });
+
+ describe('Scene激活管理', () => {
+ test('激活Scene应该正确', () => {
+ const testScene = new TestScene();
+ world.createScene('active-test', testScene);
+
+ world.setSceneActive('active-test', true);
+
+ expect(world.isSceneActive('active-test')).toBe(true);
+ expect(world.getActiveSceneCount()).toBe(1);
+ expect(testScene.beginCalled).toBe(true);
+ });
+
+ test('停用Scene应该正确', () => {
+ world.createScene('deactive-test');
+ world.setSceneActive('deactive-test', true);
+
+ world.setSceneActive('deactive-test', false);
+
+ expect(world.isSceneActive('deactive-test')).toBe(false);
+ expect(world.getActiveSceneCount()).toBe(0);
+ });
+
+ test('激活不存在的Scene应该记录警告', () => {
+ const consoleSpy = jest.spyOn(console, 'warn').mockImplementation();
+
+ world.setSceneActive('non-existent', true);
+
+ // 注意:这里需要检查具体的日志实现,可能需要调整
+ consoleSpy.mockRestore();
+ });
+ });
+
+ describe('全局System管理', () => {
+ test('添加全局System应该成功', () => {
+ const globalSystem = new TestGlobalSystem();
+
+ const addedSystem = world.addGlobalSystem(globalSystem);
+
+ expect(addedSystem).toBe(globalSystem);
+ expect(world.getGlobalSystem(TestGlobalSystem)).toBe(globalSystem);
+ });
+
+ test('重复添加相同System应该返回原System', () => {
+ const globalSystem = new TestGlobalSystem();
+
+ const firstAdd = world.addGlobalSystem(globalSystem);
+ const secondAdd = world.addGlobalSystem(globalSystem);
+
+ expect(firstAdd).toBe(secondAdd);
+ expect(firstAdd).toBe(globalSystem);
+ });
+
+ test('移除全局System应该成功', () => {
+ const globalSystem = new TestGlobalSystem();
+ world.addGlobalSystem(globalSystem);
+
+ const removed = world.removeGlobalSystem(globalSystem);
+
+ expect(removed).toBe(true);
+ expect(world.getGlobalSystem(TestGlobalSystem)).toBeNull();
+ });
+
+ test('移除不存在的System应该返回false', () => {
+ const globalSystem = new TestGlobalSystem();
+
+ const removed = world.removeGlobalSystem(globalSystem);
+
+ expect(removed).toBe(false);
+ });
+
+ test('获取不存在的System类型应该返回null', () => {
+ const system = world.getGlobalSystem(TestGlobalSystem);
+ expect(system).toBeNull();
+ });
+ });
+
+ describe('World生命周期', () => {
+ test('启动World应该正确', () => {
+ const globalSystem = new TestGlobalSystem();
+ world.addGlobalSystem(globalSystem);
+
+ world.start();
+
+ expect(world.isActive).toBe(true);
+ });
+
+ test('重复启动World应该无效果', () => {
+ world.start();
+ const firstActive = world.isActive;
+
+ world.start();
+
+ expect(world.isActive).toBe(firstActive);
+ });
+
+ test('停止World应该停用所有Scene', () => {
+ const testScene = new TestScene();
+ world.createScene('stop-test', testScene);
+ world.setSceneActive('stop-test', true);
+ world.start();
+
+ world.stop();
+
+ expect(world.isActive).toBe(false);
+ expect(world.isSceneActive('stop-test')).toBe(false);
+ });
+
+ test('销毁World应该清理所有资源', () => {
+ const testScene = new TestScene();
+ const globalSystem = new TestGlobalSystem();
+
+ world.createScene('destroy-test', testScene);
+ world.addGlobalSystem(globalSystem);
+ world.start();
+
+ world.destroy();
+
+ expect(world.sceneCount).toBe(0);
+ expect(world.isActive).toBe(false);
+ expect(testScene.endCalled).toBe(true);
+ });
+ });
+
+ describe('更新逻辑', () => {
+ test('updateGlobalSystems应该更新全局系统', () => {
+ const globalSystem = new TestGlobalSystem();
+ world.addGlobalSystem(globalSystem);
+ world.start();
+
+ // 创建测试Scene
+ const scene = world.createScene('update-test');
+ world.setSceneActive('update-test', true);
+
+ // 直接测试全局系统更新
+ world.updateGlobalSystems();
+
+ // 验证全局System被正确调用
+ expect(globalSystem.updateCount).toBeGreaterThan(0);
+ });
+
+ test('未激活的World不应该更新', () => {
+ const globalSystem = new TestGlobalSystem();
+ world.addGlobalSystem(globalSystem);
+ // 不启动World
+
+ world.updateGlobalSystems();
+
+ expect(globalSystem.updateCount).toBe(0);
+ });
+
+ test('updateScenes应该更新激活的Scene', () => {
+ const scene1 = world.createScene('scene1');
+ const scene2 = world.createScene('scene2');
+
+ scene1.addEntityProcessor(new TestSceneSystem());
+ scene2.addEntityProcessor(new TestSceneSystem());
+
+ world.start();
+ world.setSceneActive('scene1', true);
+ // scene2保持未激活
+
+ world.updateScenes();
+
+ // 这里需要根据具体的Scene更新实现来验证
+ // 由于Scene.update()的具体实现可能不同,这里主要测试调用不出错
+ expect(() => world.updateScenes()).not.toThrow();
+ });
+ });
+
+ describe('状态和统计', () => {
+ test('获取World状态应该正确', () => {
+ world.createScene('status-scene1');
+ world.createScene('status-scene2');
+ world.setSceneActive('status-scene1', true);
+ world.addGlobalSystem(new TestGlobalSystem());
+ world.start();
+
+ const status = world.getStatus();
+
+ expect(status.name).toBe('TestWorld');
+ expect(status.isActive).toBe(true);
+ expect(status.sceneCount).toBe(2);
+ expect(status.activeSceneCount).toBe(1);
+ expect(status.globalSystemCount).toBe(1);
+ expect(status.createdAt).toBeGreaterThan(0);
+ expect(status.scenes).toHaveLength(2);
+
+ const activeScene = status.scenes.find(s => s.id === 'status-scene1');
+ expect(activeScene?.isActive).toBe(true);
+
+ const inactiveScene = status.scenes.find(s => s.id === 'status-scene2');
+ expect(inactiveScene?.isActive).toBe(false);
+ });
+
+ test('获取World统计应该包含基本信息', () => {
+ world.addGlobalSystem(new TestGlobalSystem());
+
+ const scene = world.createScene('stats-scene');
+ const entity = scene.createEntity('stats-entity');
+ entity.addComponent(new TestComponent());
+
+ const stats = world.getStats();
+
+ expect(stats).toHaveProperty('totalEntities');
+ expect(stats).toHaveProperty('totalSystems');
+ expect(stats).toHaveProperty('memoryUsage');
+ expect(stats).toHaveProperty('performance');
+ expect(stats.totalSystems).toBeGreaterThanOrEqual(1);
+ });
+ });
+
+ describe('自动清理功能', () => {
+ test('自动清理应该移除空闲Scene', async () => {
+ // 创建一个启用自动清理的World
+ const autoCleanWorld = new World({
+ name: 'AutoCleanWorld',
+ autoCleanup: true,
+ maxScenes: 10
+ });
+
+ // 创建一个空Scene
+ autoCleanWorld.createScene('empty-scene');
+ autoCleanWorld.start();
+
+ // 手动触发清理检查
+ autoCleanWorld.updateScenes();
+
+ // 由于清理策略基于时间,这里主要测试不会出错
+ expect(() => autoCleanWorld.updateScenes()).not.toThrow();
+
+ autoCleanWorld.destroy();
+ });
+ });
+
+ describe('错误处理', () => {
+ test('Scene ID为空时应该创建默认ID', () => {
+ expect(() => {
+ world.createScene('');
+ }).not.toThrow();
+ });
+
+ test('极限情况下的资源管理', () => {
+ // 创建大量Scene
+ for (let i = 0; i < 5; i++) {
+ world.createScene(`scene_${i}`);
+ world.setSceneActive(`scene_${i}`, true);
+ }
+
+ // 添加多个全局System
+ for (let i = 0; i < 3; i++) {
+ world.addGlobalSystem(new TestGlobalSystem());
+ }
+
+ world.start();
+
+ // 测试批量清理
+ expect(() => world.destroy()).not.toThrow();
+ });
+ });
+});
\ No newline at end of file
diff --git a/packages/core/tests/ECS/WorldManager.test.ts b/packages/core/tests/ECS/WorldManager.test.ts
new file mode 100644
index 00000000..d656f11b
--- /dev/null
+++ b/packages/core/tests/ECS/WorldManager.test.ts
@@ -0,0 +1,464 @@
+import { WorldManager, IWorldManagerConfig } from '../../src/ECS/WorldManager';
+import { World, IWorldConfig } from '../../src/ECS/World';
+import { Scene } from '../../src/ECS/Scene';
+import { EntitySystem } from '../../src/ECS/Systems/EntitySystem';
+import { Component } from '../../src/ECS/Component';
+import { Matcher } from '../../src/ECS/Utils/Matcher';
+
+// 测试用组件
+class TestComponent extends Component {
+ public value: number = 0;
+
+ constructor(value: number = 0) {
+ super();
+ this.value = value;
+ }
+}
+
+// 测试用全局系统
+class TestGlobalSystem {
+ public readonly name = 'TestGlobalSystem';
+ public updateCount: number = 0;
+
+ public initialize(): void {
+ // 初始化
+ }
+
+ public update(): void {
+ this.updateCount++;
+ }
+
+ public reset(): void {
+ this.updateCount = 0;
+ }
+
+ public destroy(): void {
+ // 销毁
+ }
+}
+
+describe('WorldManager', () => {
+ let worldManager: WorldManager;
+
+ beforeEach(() => {
+ // 重置单例
+ WorldManager['_instance'] = null;
+ worldManager = WorldManager.getInstance();
+ });
+
+ afterEach(() => {
+ // 清理所有World
+ if (worldManager) {
+ const worldIds = worldManager.getWorldIds();
+ worldIds.forEach(id => {
+ worldManager.removeWorld(id);
+ });
+ // 清理定时器
+ worldManager.destroy();
+ }
+ WorldManager['_instance'] = null;
+ });
+
+ describe('单例模式', () => {
+ test('获取实例应该返回相同的实例', () => {
+ const instance1 = WorldManager.getInstance();
+ const instance2 = WorldManager.getInstance();
+
+ expect(instance1).toBe(instance2);
+ });
+
+ test('使用配置创建实例应该正确', () => {
+ WorldManager['_instance'] = null;
+
+ const config: IWorldManagerConfig = {
+ maxWorlds: 10,
+ autoCleanup: true,
+ debug: false
+ };
+
+ const instance = WorldManager.getInstance(config);
+
+ expect(instance).toBeDefined();
+ expect(instance).toBe(WorldManager.getInstance());
+ });
+ });
+
+ describe('World管理', () => {
+ test('创建World应该成功', () => {
+ const world = worldManager.createWorld('test-world');
+
+ expect(world).toBeDefined();
+ expect(world.name).toBe('test-world');
+ expect(worldManager.getWorld('test-world')).toBeDefined();
+ expect(worldManager.getWorldIds()).toContain('test-world');
+ });
+
+ test('创建World时传入配置应该正确', () => {
+ const worldConfig: IWorldConfig = {
+ name: 'ConfiguredWorld',
+ debug: true,
+ maxScenes: 5,
+ autoCleanup: false
+ };
+
+ const world = worldManager.createWorld('configured-world', worldConfig);
+
+ expect(world.name).toBe('ConfiguredWorld');
+ });
+
+ test('重复的World ID应该抛出错误', () => {
+ worldManager.createWorld('duplicate-world');
+
+ expect(() => {
+ worldManager.createWorld('duplicate-world');
+ }).toThrow("World ID 'duplicate-world' 已存在");
+ });
+
+ test('超出最大World数量应该抛出错误', () => {
+ WorldManager['_instance'] = null;
+ const limitedManager = WorldManager.getInstance({ maxWorlds: 2 });
+
+ limitedManager.createWorld('world1');
+ limitedManager.createWorld('world2');
+
+ expect(() => {
+ limitedManager.createWorld('world3');
+ }).toThrow("已达到最大World数量限制: 2");
+
+ // 清理
+ limitedManager.removeWorld('world1');
+ limitedManager.removeWorld('world2');
+ });
+
+ test('获取World应该正确', () => {
+ const world = worldManager.createWorld('get-world');
+ const retrievedWorld = worldManager.getWorld('get-world');
+
+ expect(retrievedWorld).toBe(world);
+ });
+
+ test('获取不存在的World应该返回null', () => {
+ const world = worldManager.getWorld('non-existent');
+ expect(world).toBeNull();
+ });
+
+ test('检查World存在性应该正确', () => {
+ expect(worldManager.getWorld('non-existent')).toBeNull();
+
+ worldManager.createWorld('exists');
+ expect(worldManager.getWorld('exists')).toBeDefined();
+ });
+
+ test('销毁World应该正确清理', () => {
+ const world = worldManager.createWorld('destroy-world');
+ world.start();
+
+ const destroyed = worldManager.removeWorld('destroy-world');
+
+ expect(destroyed).toBe(true);
+ expect(worldManager.getWorld('destroy-world')).toBeNull();
+ });
+
+ test('销毁不存在的World应该返回false', () => {
+ const destroyed = worldManager.removeWorld('non-existent');
+ expect(destroyed).toBe(false);
+ });
+
+ test('获取所有World ID应该正确', () => {
+ worldManager.createWorld('world1');
+ worldManager.createWorld('world2');
+ worldManager.createWorld('world3');
+
+ const worldIds = worldManager.getWorldIds();
+
+ expect(worldIds).toHaveLength(3);
+ expect(worldIds).toContain('world1');
+ expect(worldIds).toContain('world2');
+ expect(worldIds).toContain('world3');
+ });
+ });
+
+ describe('活跃World管理', () => {
+ test('启动World应该加入活跃列表', () => {
+ const world = worldManager.createWorld('active-world');
+
+ worldManager.setWorldActive('active-world', true);
+
+ const activeWorlds = worldManager.getActiveWorlds();
+ expect(activeWorlds).toHaveLength(1);
+ expect(activeWorlds[0]).toBe(world);
+ });
+
+ test('停止World应该从活跃列表移除', () => {
+ const world = worldManager.createWorld('inactive-world');
+ worldManager.setWorldActive('inactive-world', true);
+
+ worldManager.setWorldActive('inactive-world', false);
+
+ const activeWorlds = worldManager.getActiveWorlds();
+ expect(activeWorlds).toHaveLength(0);
+ });
+
+ test('销毁激活的World应该从活跃列表移除', () => {
+ const world = worldManager.createWorld('destroy-active');
+ worldManager.setWorldActive('destroy-active', true);
+
+ worldManager.removeWorld('destroy-active');
+
+ const activeWorlds = worldManager.getActiveWorlds();
+ expect(activeWorlds).toHaveLength(0);
+ });
+
+ test('多个World的激活状态应该独立管理', () => {
+ const world1 = worldManager.createWorld('world1');
+ const world2 = worldManager.createWorld('world2');
+ const world3 = worldManager.createWorld('world3');
+
+ worldManager.setWorldActive('world1', true);
+ worldManager.setWorldActive('world3', true);
+ // world2 保持未启动
+
+ const activeWorlds = worldManager.getActiveWorlds();
+
+ expect(activeWorlds).toHaveLength(2);
+ expect(activeWorlds).toContain(world1);
+ expect(activeWorlds).toContain(world3);
+ expect(activeWorlds).not.toContain(world2);
+ });
+ });
+
+ describe('统计和监控', () => {
+ test('获取WorldManager状态应该正确', () => {
+ worldManager.createWorld('status-world1');
+ const world2 = worldManager.createWorld('status-world2');
+ worldManager.setWorldActive('status-world2', true);
+
+ const status = worldManager.getStats();
+
+ expect(status.totalWorlds).toBe(2);
+ expect(status.activeWorlds).toBe(1);
+ expect(status.config.maxWorlds).toBeGreaterThan(0);
+ expect(status.memoryUsage).toBeGreaterThanOrEqual(0);
+ expect(status.isRunning).toBeDefined();
+ });
+
+ test('获取所有World统计应该包含详细信息', () => {
+ const world1 = worldManager.createWorld('stats-world1');
+ const world2 = worldManager.createWorld('stats-world2');
+
+ // 为world1添加一些内容
+ const scene1 = world1.createScene('scene1');
+ scene1.createEntity('entity1');
+ worldManager.setWorldActive('stats-world1', true);
+
+ // world2保持空
+
+ const allStats = worldManager.getDetailedStatus().worlds;
+
+ expect(allStats).toHaveLength(2);
+
+ const world1Stats = allStats.find(stat => stat.id === 'stats-world1');
+ const world2Stats = allStats.find(stat => stat.id === 'stats-world2');
+
+ expect(world1Stats).toBeDefined();
+ expect(world2Stats).toBeDefined();
+ expect(world1Stats?.isActive).toBe(true);
+ expect(world2Stats?.isActive).toBe(false);
+ });
+
+ test('空WorldManager的统计应该正确', () => {
+ const status = worldManager.getStats();
+ const allStats = worldManager.getDetailedStatus().worlds;
+
+ expect(status.totalWorlds).toBe(0);
+ expect(status.activeWorlds).toBe(0);
+ expect(allStats).toHaveLength(0);
+ });
+ });
+
+ describe('清理功能', () => {
+ test('清理空闲World应该移除符合条件的World', () => {
+ // 创建一个空的World
+ const emptyWorld = worldManager.createWorld('empty-world');
+
+ // 创建一个有内容的World
+ const fullWorld = worldManager.createWorld('full-world');
+ const scene = fullWorld.createScene('scene');
+ scene.createEntity('entity');
+ fullWorld.start();
+
+ // 执行清理
+ const cleanedCount = worldManager.cleanup();
+
+ // 由于清理逻辑可能基于时间或其他条件,这里主要测试不会出错
+ expect(cleanedCount).toBeGreaterThanOrEqual(0);
+ expect(() => worldManager.cleanup()).not.toThrow();
+ });
+ });
+
+ describe('World更新协调', () => {
+ test('更新所有活跃World应该正确', () => {
+ const world1 = worldManager.createWorld('update-world1');
+ const world2 = worldManager.createWorld('update-world2');
+ const world3 = worldManager.createWorld('update-world3');
+
+ // 添加一些内容到World中
+ const scene1 = world1.createScene('scene1');
+ const scene2 = world2.createScene('scene2');
+
+ scene1.createEntity('entity1');
+ scene2.createEntity('entity2');
+
+ // 启动部分World
+ worldManager.setWorldActive('update-world1', true);
+ worldManager.setWorldActive('update-world2', true);
+ // world3保持未启动
+
+ // 手动调用更新(通常由Core.update()调用)
+ const activeWorlds = worldManager.getActiveWorlds();
+
+ expect(() => {
+ activeWorlds.forEach(world => {
+ world.updateGlobalSystems();
+ world.updateScenes();
+ });
+ }).not.toThrow();
+
+ expect(activeWorlds).toHaveLength(2);
+ });
+ });
+
+ describe('边界情况和错误处理', () => {
+ test('World ID为空字符串应该抛出错误', () => {
+ expect(() => {
+ worldManager.createWorld('');
+ }).toThrow();
+ });
+
+ test('World ID为null或undefined应该抛出错误', () => {
+ expect(() => {
+ worldManager.createWorld(null as any);
+ }).toThrow();
+
+ expect(() => {
+ worldManager.createWorld(undefined as any);
+ }).toThrow();
+ });
+
+ test('极限情况下的大量World管理', () => {
+ const worldCount = 50;
+ const worldIds: string[] = [];
+
+ // 创建大量World
+ for (let i = 0; i < worldCount; i++) {
+ const worldId = `mass-world-${i}`;
+ worldIds.push(worldId);
+
+ expect(() => {
+ worldManager.createWorld(worldId);
+ }).not.toThrow();
+ }
+
+ expect(worldManager.getWorldIds()).toHaveLength(worldCount);
+
+ // 启动一半的World
+ for (let i = 0; i < worldCount / 2; i++) {
+ worldManager.setWorldActive(worldIds[i], true);
+ }
+
+ expect(worldManager.getActiveWorlds()).toHaveLength(worldCount / 2);
+
+ // 批量清理
+ worldIds.forEach(id => {
+ expect(() => {
+ worldManager.removeWorld(id);
+ }).not.toThrow();
+ });
+
+ expect(worldManager.getWorldIds()).toHaveLength(0);
+ });
+
+ test('销毁后获取World应该返回null', () => {
+ worldManager.createWorld('temp-world');
+ worldManager.removeWorld('temp-world');
+
+ expect(worldManager.getWorld('temp-world')).toBeNull();
+ });
+ });
+
+ describe('内存管理', () => {
+ test('销毁所有World后内存应该被释放', () => {
+ // 创建多个World并添加内容
+ for (let i = 0; i < 10; i++) {
+ const world = worldManager.createWorld(`memory-world-${i}`);
+ const scene = world.createScene('scene');
+
+ // 添加一些实体和系统
+ for (let j = 0; j < 5; j++) {
+ const entity = scene.createEntity(`entity-${j}`);
+ entity.addComponent(new TestComponent(j));
+ }
+
+ world.addGlobalSystem(new TestGlobalSystem());
+ worldManager.setWorldActive(`memory-world-${i}`, true);
+ }
+
+ const beforeCleanup = worldManager.getStats();
+ expect(beforeCleanup.totalWorlds).toBe(10);
+ expect(beforeCleanup.activeWorlds).toBe(10);
+
+ // 清理所有World
+ const worldIds = worldManager.getWorldIds();
+ worldIds.forEach(id => {
+ worldManager.removeWorld(id);
+ });
+
+ const afterCleanup = worldManager.getStats();
+ expect(afterCleanup.totalWorlds).toBe(0);
+ expect(afterCleanup.activeWorlds).toBe(0);
+ });
+ });
+
+ describe('配置验证', () => {
+ test('无效的maxWorlds配置应该使用默认值', () => {
+ WorldManager['_instance'] = null;
+
+ const invalidConfig: IWorldManagerConfig = {
+ maxWorlds: -1,
+ autoCleanup: true,
+ debug: true
+ };
+
+ expect(() => {
+ WorldManager.getInstance(invalidConfig);
+ }).not.toThrow();
+ });
+
+ test('配置更新应该影响后续操作', () => {
+ WorldManager['_instance'] = null;
+
+ const config: IWorldManagerConfig = {
+ maxWorlds: 3,
+ autoCleanup: true,
+ debug: true
+ };
+
+ const manager = WorldManager.getInstance(config);
+
+ // 创建到限制数量的World
+ manager.createWorld('world1');
+ manager.createWorld('world2');
+ manager.createWorld('world3');
+
+ // 第四个应该失败
+ expect(() => {
+ manager.createWorld('world4');
+ }).toThrow();
+
+ // 清理
+ manager.removeWorld('world1');
+ manager.removeWorld('world2');
+ manager.removeWorld('world3');
+ });
+ });
+});
\ No newline at end of file