实体中的线性数组换为按组件类型ID直址的稀疏数组

This commit is contained in:
YHH
2025-09-02 21:59:59 +08:00
parent 586a0e5d14
commit 94541d0abb

View File

@@ -4,18 +4,7 @@ import { EventBus } from './Core/EventBus';
import { IBigIntLike, BigIntFactory } from './Utils/BigIntCompatibility'; import { IBigIntLike, BigIntFactory } from './Utils/BigIntCompatibility';
import { createLogger } from '../Utils/Logger'; import { createLogger } from '../Utils/Logger';
import { getComponentInstanceTypeName, getComponentTypeName } from './Decorators'; import { getComponentInstanceTypeName, getComponentTypeName } from './Decorators';
import type { IScene } from './IScene';
// Forward declaration to avoid circular dependency
interface IScene {
readonly name: string;
readonly componentStorageManager: import('./Core/ComponentStorage').ComponentStorageManager;
readonly querySystem: import('./Core/QuerySystem').QuerySystem;
readonly eventSystem: import('./Core/EventSystem').TypeSafeEventSystem;
readonly entities: import('./Utils/EntityList').EntityList;
addEntity(entity: Entity): Entity;
initialize(): void;
update(deltaTime: number): void;
}
/** /**
* 实体比较器 * 实体比较器
@@ -175,11 +164,9 @@ export class Entity {
private _componentMask: IBigIntLike = BigIntFactory.zero(); private _componentMask: IBigIntLike = BigIntFactory.zero();
/** /**
* 组件类型到索引的映射 * 组件类型ID直址的稀疏数组
*
* 用于快速定位组件在数组中的位置。
*/ */
private _componentTypeToIndex = new Map<ComponentType, number>(); private _componentsByTypeId: (Component | undefined)[] = [];
/** /**
* 构造函数 * 构造函数
@@ -356,13 +343,14 @@ export class Entity {
ComponentRegistry.register(componentType); ComponentRegistry.register(componentType);
} }
const typeId = ComponentRegistry.getBitIndex(componentType);
// 设置组件的实体引用 // 设置组件的实体引用
component.entity = this; component.entity = this;
// 添加到组件列表并建立索引映射 // 直址存储
const index = this.components.length; this._componentsByTypeId[typeId] = component;
this.components.push(component); this.components.push(component);
this._componentTypeToIndex.set(componentType, index);
// 更新位掩码 // 更新位掩码
const componentMask = ComponentRegistry.getBitMask(componentType); const componentMask = ComponentRegistry.getBitMask(componentType);
@@ -438,31 +426,33 @@ export class Entity {
return null; return null;
} }
// 尝试从索引映射获取O(1) // 直址访问
const index = this._componentTypeToIndex.get(type); const typeId = ComponentRegistry.getBitIndex(type);
if (index !== undefined && index < this.components.length) { const component = this._componentsByTypeId[typeId];
const component = this.components[index];
if (component && component.constructor === type) { if (component && component.constructor === type) {
return component as T; return component as T;
}
} }
// 如果场景有组件存储管理器,从存储器获取 // 如果场景有组件存储管理器,从存储器获取
if (this.scene && this.scene.componentStorageManager) { if (this.scene && this.scene.componentStorageManager) {
const component = this.scene.componentStorageManager.getComponent(this.id, type); const storageComponent = this.scene.componentStorageManager.getComponent(this.id, type);
if (component) { if (storageComponent) {
// 重建索引映射 // 同步到稀疏数组
this.rebuildComponentIndex(); this._componentsByTypeId[typeId] = storageComponent;
return component; if (!this.components.includes(storageComponent)) {
this.components.push(storageComponent);
}
return storageComponent;
} }
} }
// 最后回退到线性搜索并重建索引O(n)但n很小且很少发生 // 最后回退到线性搜索
for (let i = 0; i < this.components.length; i++) { for (let i = 0; i < this.components.length; i++) {
const component = this.components[i]; const component = this.components[i];
if (component instanceof type) { if (component instanceof type) {
// 重建索引映射 // 同步到稀疏数组
this._componentTypeToIndex.set(type, i); this._componentsByTypeId[typeId] = component;
return component as T; return component as T;
} }
} }
@@ -472,18 +462,6 @@ export class Entity {
/**
* 重建组件索引映射
*/
private rebuildComponentIndex(): void {
this._componentTypeToIndex.clear();
for (let i = 0; i < this.components.length; i++) {
const component = this.components[i];
const componentType = component.constructor as ComponentType;
this._componentTypeToIndex.set(componentType, i);
}
}
/** /**
* 检查实体是否有指定类型的组件 * 检查实体是否有指定类型的组件
@@ -526,19 +504,20 @@ export class Entity {
public removeComponent(component: Component): void { public removeComponent(component: Component): void {
const componentType = component.constructor as ComponentType; const componentType = component.constructor as ComponentType;
// 从组件列表中移除 // 从稀疏数组中移除
if (ComponentRegistry.isRegistered(componentType)) {
const typeId = ComponentRegistry.getBitIndex(componentType);
this._componentsByTypeId[typeId] = undefined;
// 更新位掩码
const componentMask = ComponentRegistry.getBitMask(componentType);
this._componentMask = this._componentMask.and(componentMask.not());
}
// 从迭代数组中移除
const index = this.components.indexOf(component); const index = this.components.indexOf(component);
if (index !== -1) { if (index !== -1) {
this.components.splice(index, 1); this.components.splice(index, 1);
// 重建索引映射(因为数组索引发生了变化)
this.rebuildComponentIndex();
}
// 更新位掩码
if (ComponentRegistry.isRegistered(componentType)) {
const componentMask = ComponentRegistry.getBitMask(componentType);
this._componentMask = this._componentMask.and(componentMask.not());
} }
// 从组件存储管理器中移除 // 从组件存储管理器中移除
@@ -598,8 +577,8 @@ export class Entity {
// 复制组件列表,避免在迭代时修改 // 复制组件列表,避免在迭代时修改
const componentsToRemove = [...this.components]; const componentsToRemove = [...this.components];
// 清空索引和位掩码 // 清空稀疏数组和位掩码
this._componentTypeToIndex.clear(); this._componentsByTypeId.length = 0;
this._componentMask = BigIntFactory.zero(); this._componentMask = BigIntFactory.zero();
// 移除组件 // 移除组件
@@ -1007,7 +986,7 @@ export class Entity {
childCount: this._children.length, childCount: this._children.length,
childIds: this._children.map(c => c.id), childIds: this._children.map(c => c.id),
depth: this.getDepth(), depth: this.getDepth(),
indexMappingSize: this._componentTypeToIndex.size indexMappingSize: this._componentsByTypeId.filter(c => c !== undefined).length
}; };
} }
} }