新增scenemanager,重构core类减少多世界造成的性能压力

This commit is contained in:
YHH
2025-10-09 23:33:11 +08:00
parent 79f7c89e23
commit 7339e7ecec
10 changed files with 876 additions and 1103 deletions

View File

@@ -2,6 +2,7 @@ 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 { SceneManager } from '../../../src/ECS/SceneManager';
import { EntitySystem } from '../../../src/ECS/Systems/EntitySystem';
import { Component } from '../../../src/ECS/Component';
import { Matcher } from '../../../src/ECS/Utils/Matcher';
@@ -10,580 +11,185 @@ 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++;
}
}
/**
* World与Core集成测试
*
* 注意v3.0重构后Core不再直接管理Scene/World
* - 场景管理由 SceneManager 负责
* - 多世界管理由 WorldManager 负责
* - Core 仅负责全局服务Timer、Performance等
*
* 大部分旧的集成测试已移至 SceneManager.test.ts 和 WorldManager.test.ts
*/
describe('World与Core集成测试', () => {
let worldManager: WorldManager;
let sceneManager: SceneManager;
beforeEach(() => {
// 重置Core和WorldManager
if ((Core as any)._instance) {
(Core as any)._instance = null;
// 重置Core
if (Core.Instance) {
Core.destroy();
}
WorldManager['_instance'] = null;
Core.create({ debug: false });
// WorldManager和SceneManager不再是单例
worldManager = new WorldManager();
sceneManager = new SceneManager();
});
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;
if (sceneManager) {
sceneManager.destroy();
}
if (worldManager) {
worldManager.destroy();
}
if (Core.Instance) {
Core.destroy();
}
WorldManager['_instance'] = null;
});
describe('融合设计基础功能', () => {
test('单Scene模式应该保持向后兼容', () => {
Core.create({ debug: false });
// 传统单Scene用法
describe('基础功能', () => {
test('Core应该能够独立运行', () => {
expect(Core.Instance).toBeDefined();
// Core.update 仅更新全局服务
Core.update(0.016);
});
test('SceneManager应该能够独立管理场景', () => {
const scene = new Scene();
scene.name = 'TestScene';
Core.setScene(scene);
const retrievedScene = Core.getScene();
expect(retrievedScene).toBe(scene);
expect(retrievedScene?.name).toBe('TestScene');
sceneManager.setScene(scene);
expect(sceneManager.currentScene).toBe(scene);
expect(sceneManager.hasScene).toBe(true);
// 场景更新独立于Core
sceneManager.update();
});
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);
test('WorldManager应该能够独立管理多个World', () => {
const world1 = worldManager.createWorld('world1');
const world2 = worldManager.createWorld('world2');
expect(worldManager.worldCount).toBe(2);
expect(worldManager.getWorld('world1')).toBe(world1);
expect(worldManager.getWorld('world2')).toBe(world2);
});
});
describe('默认World机制', () => {
test('设置Scene应该自动创建默认World', () => {
Core.create({ debug: false });
describe('组合使用', () => {
test('Core + SceneManager 应该正确协作', () => {
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);
sceneManager.setScene(scene);
const entity = scene.createEntity('TestEntity');
entity.addComponent(new TestComponent(42));
// 游戏循环
Core.update(0.016); // 更新全局服务
sceneManager.update(); // 更新场景
expect(scene.entities.count).toBe(1);
});
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('Core + WorldManager 应该正确协作', () => {
const world = worldManager.createWorld('test-world');
const scene = world.createScene('main', new Scene());
world.setActive(true);
// 游戏循环
Core.update(0.016); // 更新全局服务
worldManager.updateAll(); // 更新所有World
expect(world.isActive).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();
test('World的全局系统应该能够正常工作', () => {
const world = worldManager.createWorld('test-world');
const globalSystem = new NetworkGlobalSystem();
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);
world.setActive(true);
// 更新World
worldManager.updateAll();
expect(globalSystem.syncCount).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);
describe('隔离性测试', () => {
test('多个WorldManager实例应该完全隔离', () => {
const manager1 = new WorldManager();
const manager2 = new WorldManager();
manager1.createWorld('world1');
manager2.createWorld('world2');
expect(manager1.getWorld('world1')).toBeDefined();
expect(manager1.getWorld('world2')).toBeNull();
expect(manager2.getWorld('world2')).toBeDefined();
expect(manager2.getWorld('world1')).toBeNull();
// 清理
manager1.destroy();
manager2.destroy();
});
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);
test('多个SceneManager实例应该完全隔离', () => {
const sm1 = new SceneManager();
const sm2 = new SceneManager();
const scene1 = new Scene();
const scene2 = new Scene();
sm1.setScene(scene1);
sm2.setScene(scene2);
expect(sm1.currentScene).toBe(scene1);
expect(sm2.currentScene).toBe(scene2);
// 清理
sm1.destroy();
sm2.destroy();
});
});
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();
});
});
});
});

View File

@@ -39,13 +39,12 @@ class TestGlobalSystem {
describe('WorldManager', () => {
let worldManager: WorldManager;
beforeEach(() => {
// 重置单
WorldManager['_instance'] = null;
worldManager = WorldManager.getInstance();
// WorldManager不再是单例直接创建新实
worldManager = new WorldManager();
});
afterEach(() => {
// 清理所有World
if (worldManager) {
@@ -56,33 +55,40 @@ describe('WorldManager', () => {
// 清理定时器
worldManager.destroy();
}
WorldManager['_instance'] = null;
});
describe('单例模式', () => {
test('获取实例应该返回相同的实例', () => {
const instance1 = WorldManager.getInstance();
const instance2 = WorldManager.getInstance();
expect(instance1).toBe(instance2);
describe('实例化', () => {
test('可以创建多个独立的WorldManager实例', () => {
const manager1 = new WorldManager();
const manager2 = new WorldManager();
expect(manager1).not.toBe(manager2);
manager1.createWorld('world1');
expect(manager2.getWorld('world1')).toBeNull();
// 清理
manager1.destroy();
manager2.destroy();
});
test('使用配置创建实例应该正确', () => {
WorldManager['_instance'] = null;
const config: IWorldManagerConfig = {
maxWorlds: 10,
autoCleanup: true,
debug: false
};
const instance = WorldManager.getInstance(config);
const instance = new WorldManager(config);
expect(instance).toBeDefined();
expect(instance).toBe(WorldManager.getInstance());
expect(instance.worldCount).toBe(0);
// 清理
instance.destroy();
});
});
describe('World管理', () => {
test('创建World应该成功', () => {
const world = worldManager.createWorld('test-world');
@@ -115,19 +121,17 @@ describe('WorldManager', () => {
});
test('超出最大World数量应该抛出错误', () => {
WorldManager['_instance'] = null;
const limitedManager = WorldManager.getInstance({ maxWorlds: 2 });
const limitedManager = new WorldManager({ maxWorlds: 2 });
limitedManager.createWorld('world1');
limitedManager.createWorld('world2');
expect(() => {
limitedManager.createWorld('world3');
}).toThrow("已达到最大World数量限制: 2");
// 清理
limitedManager.removeWorld('world1');
limitedManager.removeWorld('world2');
limitedManager.destroy();
});
test('获取World应该正确', () => {
@@ -430,35 +434,31 @@ describe('WorldManager', () => {
};
expect(() => {
WorldManager.getInstance(invalidConfig);
new WorldManager(invalidConfig);
}).not.toThrow();
});
test('配置更新应该影响后续操作', () => {
WorldManager['_instance'] = null;
test('配置应该正确应用于新实例', () => {
const config: IWorldManagerConfig = {
maxWorlds: 3,
autoCleanup: true,
debug: true
};
const manager = WorldManager.getInstance(config);
const manager = new WorldManager(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');
manager.destroy();
});
});
});