diff --git a/packages/core/src/ECS/Scene.ts b/packages/core/src/ECS/Scene.ts index 8980eab9..317496e1 100644 --- a/packages/core/src/ECS/Scene.ts +++ b/packages/core/src/ECS/Scene.ts @@ -143,6 +143,14 @@ export class Scene implements IScene { */ private _maxErrorCount: number = 10; + /** + * 系统添加计数器 + * + * 用于为每个添加的系统分配唯一的添加顺序,保证排序稳定性 + * Counter for assigning unique add order to each system for stable sorting + */ + private _systemAddCounter: number = 0; + /** * 获取场景中所有已注册的EntitySystem * @@ -180,10 +188,15 @@ export class Scene implements IScene { } /** - * 按updateOrder排序系统 + * 按 updateOrder 排序系统,相同时按 addOrder 保证稳定性 + * Sort systems by updateOrder, use addOrder as secondary key for stability */ private _sortSystemsByUpdateOrder(systems: EntitySystem[]): EntitySystem[] { - return systems.sort((a, b) => a.updateOrder - b.updateOrder); + return systems.sort((a, b) => { + const orderDiff = a.updateOrder - b.updateOrder; + if (orderDiff !== 0) return orderDiff; + return a.addOrder - b.addOrder; + }); } /** @@ -707,6 +720,9 @@ export class Scene implements IScene { system.scene = this; + // 分配添加顺序,用于稳定排序 | Assign add order for stable sorting + system.addOrder = this._systemAddCounter++; + system.setPerformanceMonitor(this.performanceMonitor); const metadata = getSystemMetadata(constructor); diff --git a/packages/core/src/ECS/Systems/EntitySystem.ts b/packages/core/src/ECS/Systems/EntitySystem.ts index 446ed87e..e7128604 100644 --- a/packages/core/src/ECS/Systems/EntitySystem.ts +++ b/packages/core/src/ECS/Systems/EntitySystem.ts @@ -66,6 +66,12 @@ interface EventListenerRecord { */ export abstract class EntitySystem implements ISystemBase, IService { private _updateOrder: number; + /** + * 添加顺序,用于 updateOrder 相同时的稳定排序 + * Add order for stable sorting when updateOrder is the same + * @internal + */ + private _addOrder: number; private _enabled: boolean; private _performanceMonitor: PerformanceMonitor | null; private _systemName: string; @@ -116,6 +122,24 @@ export abstract class EntitySystem implements ISystemBase, IService { this.setUpdateOrder(value); } + /** + * 获取系统的添加顺序 + * Get the add order of the system + * @internal + */ + public get addOrder(): number { + return this._addOrder; + } + + /** + * 设置系统的添加顺序(由 Scene 在添加时设置) + * Set the add order of the system (set by Scene when adding) + * @internal + */ + public set addOrder(value: number) { + this._addOrder = value; + } + /** * 获取系统的启用状态 */ @@ -139,6 +163,7 @@ export abstract class EntitySystem implements ISystemBase, IService { constructor(matcher?: Matcher) { this._updateOrder = 0; + this._addOrder = 0; this._enabled = true; this._performanceMonitor = null; this._systemName = getSystemInstanceTypeName(this); diff --git a/packages/core/tests/ECS/Scene.test.ts b/packages/core/tests/ECS/Scene.test.ts index 1e82d94d..d8ad3358 100644 --- a/packages/core/tests/ECS/Scene.test.ts +++ b/packages/core/tests/ECS/Scene.test.ts @@ -825,5 +825,106 @@ describe('Scene - 场景管理系统测试', () => { expect(scene.entities.count).toBe(2); }); }); + + describe('系统排序稳定性', () => { + test('相同 updateOrder 的系统应按添加顺序稳定排序', () => { + // 创建多个 updateOrder 都为 0 的系统 + // Create multiple systems with updateOrder = 0 + class SystemA extends EntitySystem { + name = 'SystemA'; + constructor() { super(); } + } + class SystemB extends EntitySystem { + name = 'SystemB'; + constructor() { super(); } + } + class SystemC extends EntitySystem { + name = 'SystemC'; + constructor() { super(); } + } + + const systemA = new SystemA(); + const systemB = new SystemB(); + const systemC = new SystemC(); + + // 按 A, B, C 顺序添加 + scene.addEntityProcessor(systemA); + scene.addEntityProcessor(systemB); + scene.addEntityProcessor(systemC); + + // 验证 addOrder 按添加顺序递增 + expect(systemA.addOrder).toBe(0); + expect(systemB.addOrder).toBe(1); + expect(systemC.addOrder).toBe(2); + + // 验证系统列表按添加顺序排列 + const systems = scene.systems; + expect(systems[0]).toBe(systemA); + expect(systems[1]).toBe(systemB); + expect(systems[2]).toBe(systemC); + }); + + test('updateOrder 优先于 addOrder 排序', () => { + class SystemA extends EntitySystem { + name = 'SystemA'; + constructor() { super(); } + } + class SystemB extends EntitySystem { + name = 'SystemB'; + constructor() { super(); } + } + class SystemC extends EntitySystem { + name = 'SystemC'; + constructor() { super(); } + } + + const systemA = new SystemA(); + const systemB = new SystemB(); + const systemC = new SystemC(); + + // 按 A, B, C 顺序添加,但设置不同的 updateOrder + scene.addEntityProcessor(systemA); + systemA.updateOrder = 10; + + scene.addEntityProcessor(systemB); + systemB.updateOrder = 5; + + scene.addEntityProcessor(systemC); + systemC.updateOrder = 5; // 与 B 相同 + + // 验证排序:B(5,1), C(5,2), A(10,0) + const systems = scene.systems; + expect(systems[0]).toBe(systemB); // updateOrder=5, addOrder=1 + expect(systems[1]).toBe(systemC); // updateOrder=5, addOrder=2 + expect(systems[2]).toBe(systemA); // updateOrder=10, addOrder=0 + }); + + test('多次重新排序后仍保持稳定性', () => { + class SystemA extends EntitySystem { + name = 'SystemA'; + constructor() { super(); } + } + class SystemB extends EntitySystem { + name = 'SystemB'; + constructor() { super(); } + } + + const systemA = new SystemA(); + const systemB = new SystemB(); + + scene.addEntityProcessor(systemA); + scene.addEntityProcessor(systemB); + + // 多次触发重新排序 + for (let i = 0; i < 10; i++) { + scene.markSystemsOrderDirty(); + const systems = scene.systems; + + // 每次排序后顺序应该相同 + expect(systems[0]).toBe(systemA); + expect(systems[1]).toBe(systemB); + } + }); + }); }); }); \ No newline at end of file