133 lines
4.7 KiB
TypeScript
133 lines
4.7 KiB
TypeScript
import { Scene } from '../../../src/ECS/Scene';
|
|
import { Entity } from '../../../src/ECS/Entity';
|
|
import { Component } from '../../../src/ECS/Component';
|
|
import { EntitySystem } from '../../../src/ECS/Systems/EntitySystem';
|
|
import { ComponentTypeManager } from '../../../src/ECS/Utils/ComponentTypeManager';
|
|
|
|
class TestComponent extends Component {
|
|
public value: number = 0;
|
|
|
|
constructor(...args: unknown[]) {
|
|
super();
|
|
const [value = 0] = args as [number?];
|
|
this.value = value;
|
|
}
|
|
}
|
|
|
|
class TrackingSystem extends EntitySystem {
|
|
public initializeCallCount = 0;
|
|
public onChangedCallCount = 0;
|
|
public trackedEntities: Entity[] = [];
|
|
|
|
public override initialize(): void {
|
|
// 必须先调用父类的initialize来检查防重复逻辑
|
|
const wasInitialized = (this as any)._initialized;
|
|
super.initialize();
|
|
|
|
// 只有在真正执行初始化时才增加计数
|
|
if (!wasInitialized) {
|
|
this.initializeCallCount++;
|
|
}
|
|
}
|
|
|
|
public onChanged(entity: Entity): void {
|
|
this.onChangedCallCount++;
|
|
if (this.isInterestedEntity(entity)) {
|
|
if (!this.trackedEntities.includes(entity)) {
|
|
this.trackedEntities.push(entity);
|
|
}
|
|
} else {
|
|
const index = this.trackedEntities.indexOf(entity);
|
|
if (index !== -1) {
|
|
this.trackedEntities.splice(index, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
public isInterestedEntity(entity: Entity): boolean {
|
|
return entity.hasComponent(TestComponent);
|
|
}
|
|
}
|
|
|
|
describe('系统多次初始化问题测试', () => {
|
|
let scene: Scene;
|
|
let system: TrackingSystem;
|
|
|
|
beforeEach(() => {
|
|
ComponentTypeManager.instance.reset();
|
|
scene = new Scene();
|
|
system = new TrackingSystem();
|
|
});
|
|
|
|
test('系统被多次添加到场景 - 应该防止重复初始化', () => {
|
|
const entity = scene.createEntity('TestEntity');
|
|
entity.addComponent(new TestComponent(10));
|
|
|
|
// 第一次添加系统
|
|
scene.addEntityProcessor(system);
|
|
expect(system.initializeCallCount).toBe(1);
|
|
expect(system.trackedEntities.length).toBe(1);
|
|
expect(system.onChangedCallCount).toBe(1);
|
|
|
|
// 再次添加同一个系统 - 应该被忽略
|
|
scene.addEntityProcessor(system);
|
|
expect(system.initializeCallCount).toBe(1); // 不应该增加
|
|
expect(system.trackedEntities.length).toBe(1); // 实体不应该重复
|
|
expect(system.onChangedCallCount).toBe(1); // onChanged不应该重复调用
|
|
});
|
|
|
|
test('手动多次调用initialize - 应该防止重复处理', () => {
|
|
const entity = scene.createEntity('TestEntity');
|
|
entity.addComponent(new TestComponent(10));
|
|
|
|
scene.addEntityProcessor(system);
|
|
expect(system.initializeCallCount).toBe(1);
|
|
expect(system.trackedEntities.length).toBe(1);
|
|
expect(system.onChangedCallCount).toBe(1);
|
|
|
|
// 手动再次调用initialize - 应该被防止
|
|
system.initialize();
|
|
expect(system.initializeCallCount).toBe(1); // 不应该增加
|
|
expect(system.onChangedCallCount).toBe(1); // onChanged不应该重复调用
|
|
expect(system.trackedEntities.length).toBe(1);
|
|
});
|
|
|
|
test('系统被移除后重新添加 - 应该重新初始化', () => {
|
|
const entity = scene.createEntity('TestEntity');
|
|
entity.addComponent(new TestComponent(10));
|
|
|
|
// 添加系统
|
|
scene.addEntityProcessor(system);
|
|
expect(system.initializeCallCount).toBe(1);
|
|
expect(system.trackedEntities.length).toBe(1);
|
|
|
|
// 移除系统
|
|
scene.removeEntityProcessor(system);
|
|
|
|
// 重新添加系统 - 应该重新初始化
|
|
scene.addEntityProcessor(system);
|
|
expect(system.initializeCallCount).toBe(2); // 应该重新初始化
|
|
expect(system.trackedEntities.length).toBe(1);
|
|
});
|
|
|
|
test('多个实体的重复初始化应该被防止', () => {
|
|
// 创建多个实体
|
|
const entities = [];
|
|
for (let i = 0; i < 5; i++) {
|
|
const entity = scene.createEntity(`Entity${i}`);
|
|
entity.addComponent(new TestComponent(i));
|
|
entities.push(entity);
|
|
}
|
|
|
|
scene.addEntityProcessor(system);
|
|
expect(system.initializeCallCount).toBe(1);
|
|
expect(system.trackedEntities.length).toBe(5);
|
|
expect(system.onChangedCallCount).toBe(5);
|
|
|
|
// 手动再次初始化 - 应该被防止
|
|
system.initialize();
|
|
expect(system.initializeCallCount).toBe(1); // 不应该增加
|
|
expect(system.onChangedCallCount).toBe(5); // 不应该重复处理
|
|
expect(system.trackedEntities.length).toBe(5);
|
|
});
|
|
}); |