perf(core): 优化 EntitySystem 迭代性能,添加 CommandBuffer 延迟命令 (#281)
* perf(core): 优化 EntitySystem 迭代性能,添加 CommandBuffer 延迟命令 ReactiveQuery 快照优化: - 添加快照机制,避免每帧拷贝数组 - 只在实体列表变化时创建新快照 - 静态场景下多个系统共享同一快照 CommandBuffer 延迟命令系统: - 支持延迟添加/移除组件、销毁实体、设置实体激活状态 - 每个系统拥有独立的 commands 属性 - 命令在帧末统一执行,避免迭代过程中修改实体列表 Scene 更新: - 在 lateUpdate 后自动刷新所有系统的命令缓冲区 文档: - 更新系统文档,添加 CommandBuffer 使用说明 * fix(ci): upgrade first-interaction action to v1.3.0 Fix Docker build failure in welcome workflow. * fix(ci): upgrade pnpm/action-setup to v4 and fix unused import - Upgrade pnpm/action-setup@v2 to v4 in all workflow files - Remove unused CommandType import in CommandBuffer.test.ts * fix(ci): remove duplicate pnpm version specification
This commit is contained in:
@@ -10,6 +10,7 @@ import type { EventListenerConfig, TypeSafeEventSystem, EventHandler } from '../
|
||||
import type { ComponentConstructor, ComponentInstance } from '../../Types/TypeHelpers';
|
||||
import type { IService } from '../../Core/ServiceContainer';
|
||||
import { EntityCache } from './EntityCache';
|
||||
import { CommandBuffer } from '../Core/CommandBuffer';
|
||||
|
||||
/**
|
||||
* 事件监听器记录
|
||||
@@ -93,6 +94,30 @@ export abstract class EntitySystem implements ISystemBase, IService {
|
||||
*/
|
||||
private _entityCache: EntityCache;
|
||||
|
||||
/**
|
||||
* 命令缓冲区 - 用于延迟执行实体操作
|
||||
* Command buffer - for deferred entity operations
|
||||
*
|
||||
* 在 process() 中使用 commands 可以避免迭代过程中修改实体列表,
|
||||
* 提高性能并保证迭代安全。命令会在帧末由 Scene 统一执行。
|
||||
*
|
||||
* Using commands in process() avoids modifying entity list during iteration,
|
||||
* improving performance and ensuring iteration safety. Commands are executed by Scene at end of frame.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* protected process(entities: readonly Entity[]): void {
|
||||
* for (const entity of entities) {
|
||||
* if (shouldDie(entity)) {
|
||||
* // 延迟执行,不影响当前迭代
|
||||
* this.commands.destroyEntity(entity);
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
protected readonly commands: CommandBuffer = new CommandBuffer();
|
||||
|
||||
/**
|
||||
* 获取系统处理的实体列表
|
||||
*/
|
||||
@@ -191,6 +216,9 @@ export abstract class EntitySystem implements ISystemBase, IService {
|
||||
|
||||
public set scene(value: Scene | null) {
|
||||
this._scene = value;
|
||||
// 同步更新 CommandBuffer 的场景引用
|
||||
// Sync CommandBuffer scene reference
|
||||
this.commands.setScene(value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -599,11 +627,9 @@ export abstract class EntitySystem implements ISystemBase, IService {
|
||||
try {
|
||||
this.onBegin();
|
||||
// 查询实体并存储到帧缓存中
|
||||
// 响应式查询会自动维护最新的实体列表,updateEntityTracking会在检测到变化时invalidate
|
||||
const queriedEntities = this.queryEntities();
|
||||
// 创建数组副本以防止迭代过程中数组被修改
|
||||
// Create a copy to prevent array modification during iteration
|
||||
const entities = [...queriedEntities];
|
||||
// ReactiveQuery.getEntities() 返回的是安全快照,只在实体变化时才创建新数组
|
||||
// ReactiveQuery.getEntities() returns a safe snapshot, only creates new array when entities change
|
||||
const entities = this.queryEntities();
|
||||
this._entityCache.setFrame(entities);
|
||||
entityCount = entities.length;
|
||||
|
||||
@@ -630,10 +656,8 @@ export abstract class EntitySystem implements ISystemBase, IService {
|
||||
// 在 update 和 lateUpdate 之间可能有新组件被添加(事件驱动设计)
|
||||
// Re-query entities to get the latest list
|
||||
// New components may have been added between update and lateUpdate (event-driven design)
|
||||
const queriedEntities = this.queryEntities();
|
||||
// 创建数组副本以防止迭代过程中数组被修改
|
||||
// Create a copy to prevent array modification during iteration
|
||||
const entities = [...queriedEntities];
|
||||
// ReactiveQuery.getEntities() 返回的是安全快照,只在实体变化时才创建新数组
|
||||
const entities = this.queryEntities();
|
||||
this._entityCache.setFrame(entities);
|
||||
entityCount = entities.length;
|
||||
this.lateProcess(entities);
|
||||
@@ -645,6 +669,19 @@ export abstract class EntitySystem implements ISystemBase, IService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行命令缓冲区中的所有延迟命令
|
||||
* Flush all deferred commands in the command buffer
|
||||
*
|
||||
* 由 Scene 在帧末自动调用。
|
||||
* Called automatically by Scene at end of frame.
|
||||
*
|
||||
* @returns 执行的命令数量 | Number of commands executed
|
||||
*/
|
||||
public flushCommands(): number {
|
||||
return this.commands.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* 在系统处理开始前调用
|
||||
*
|
||||
@@ -937,6 +974,10 @@ export abstract class EntitySystem implements ISystemBase, IService {
|
||||
this._entityCache.clearAll();
|
||||
this._entityIdMap = null;
|
||||
|
||||
// 清理命令缓冲区
|
||||
// Clear command buffer
|
||||
this.commands.dispose();
|
||||
|
||||
// 重置状态
|
||||
this._initialized = false;
|
||||
this._scene = null;
|
||||
|
||||
Reference in New Issue
Block a user