Merge pull request #69 from 0MirageTank0/master

优化ArchetypeSystem性能
This commit is contained in:
YHH
2025-09-30 13:31:11 +08:00
committed by GitHub
3 changed files with 55 additions and 40 deletions

View File

@@ -1,11 +1,11 @@
import { Entity } from '../Entity'; import {Entity} from '../Entity';
import { ComponentType } from './ComponentStorage'; import {ComponentType} from './ComponentStorage';
import { getComponentTypeName } from '../Decorators'; import {BitMask64Data, ComponentTypeManager} from "../Utils";
/** /**
* 原型标识符 * 原型标识符
*/ */
export type ArchetypeId = string; export type ArchetypeId = BitMask64Data;
/** /**
* 原型数据结构 * 原型数据结构
@@ -36,7 +36,7 @@ export interface ArchetypeQueryResult {
*/ */
export class ArchetypeSystem { export class ArchetypeSystem {
/** 所有原型的映射表 */ /** 所有原型的映射表 */
private _archetypes = new Map<ArchetypeId, Archetype>(); private _archetypes = new Map<number, Map<number, Archetype>>();
/** 实体到原型的映射 */ /** 实体到原型的映射 */
private _entityToArchetype = new Map<Entity, Archetype>(); private _entityToArchetype = new Map<Entity, Archetype>();
@@ -47,8 +47,8 @@ export class ArchetypeSystem {
/** 实体组件类型缓存 */ /** 实体组件类型缓存 */
private _entityComponentTypesCache = new Map<Entity, ComponentType[]>(); private _entityComponentTypesCache = new Map<Entity, ComponentType[]>();
/** 原型ID缓存 */ /** 所有原型 */
private _archetypeIdCache = new Map<string, ArchetypeId>(); private _allArchetypes: Archetype[] = [];
/** /**
* 添加实体到原型系统 * 添加实体到原型系统
@@ -57,7 +57,7 @@ export class ArchetypeSystem {
const componentTypes = this.getEntityComponentTypes(entity); const componentTypes = this.getEntityComponentTypes(entity);
const archetypeId = this.generateArchetypeId(componentTypes); const archetypeId = this.generateArchetypeId(componentTypes);
let archetype = this._archetypes.get(archetypeId); let archetype = this.getArchetype(archetypeId);
if (!archetype) { if (!archetype) {
archetype = this.createArchetype(componentTypes); archetype = this.createArchetype(componentTypes);
} }
@@ -103,16 +103,13 @@ export class ArchetypeSystem {
return; return;
} }
const affectedComponentTypes = new Set<ComponentType>();
// 从旧原型中移除实体 // 从旧原型中移除实体
if (currentArchetype) { if (currentArchetype) {
currentArchetype.entities.delete(entity); currentArchetype.entities.delete(entity);
currentArchetype.componentTypes.forEach(type => affectedComponentTypes.add(type));
} }
// 获取或创建新原型 // 获取或创建新原型
let newArchetype = this._archetypes.get(newArchetypeId); let newArchetype = this.getArchetype(newArchetypeId);
if (!newArchetype) { if (!newArchetype) {
newArchetype = this.createArchetype(newComponentTypes); newArchetype = this.createArchetype(newComponentTypes);
} }
@@ -120,7 +117,6 @@ export class ArchetypeSystem {
// 将实体添加到新原型 // 将实体添加到新原型
newArchetype.entities.add(entity); newArchetype.entities.add(entity);
this._entityToArchetype.set(entity, newArchetype); this._entityToArchetype.set(entity, newArchetype);
newComponentTypes.forEach(type => affectedComponentTypes.add(type));
// 更新组件索引 // 更新组件索引
if (currentArchetype) { if (currentArchetype) {
@@ -139,7 +135,7 @@ export class ArchetypeSystem {
let totalEntities = 0; let totalEntities = 0;
if (operation === 'AND') { if (operation === 'AND') {
for (const archetype of this._archetypes.values()) { for (const archetype of this._allArchetypes) {
if (this.archetypeContainsAllComponents(archetype, componentTypes)) { if (this.archetypeContainsAllComponents(archetype, componentTypes)) {
matchingArchetypes.push(archetype); matchingArchetypes.push(archetype);
totalEntities += archetype.entities.size; totalEntities += archetype.entities.size;
@@ -180,7 +176,7 @@ export class ArchetypeSystem {
* 获取所有原型 * 获取所有原型
*/ */
public getAllArchetypes(): Archetype[] { public getAllArchetypes(): Archetype[] {
return Array.from(this._archetypes.values()); return this._allArchetypes.slice();
} }
/** /**
@@ -191,7 +187,28 @@ export class ArchetypeSystem {
this._entityToArchetype.clear(); this._entityToArchetype.clear();
this._componentToArchetypes.clear(); this._componentToArchetypes.clear();
this._entityComponentTypesCache.clear(); this._entityComponentTypesCache.clear();
this._archetypeIdCache.clear(); this._allArchetypes = [];
}
/**
* 根据原型ID获取原型
* @param archetypeId
* @private
*/
private getArchetype(archetypeId: ArchetypeId): Archetype | undefined {
return this._archetypes.get(archetypeId.hi)?.get(archetypeId.lo);
}
/**
* 更新所有原型数组
*/
private updateAllArchetypeArrays(): void {
this._allArchetypes = [];
for (const [, innerMap] of this._archetypes) {
for (const [, archetype] of innerMap) {
this._allArchetypes.push(archetype);
}
}
} }
/** /**
@@ -210,18 +227,8 @@ export class ArchetypeSystem {
* 生成原型ID * 生成原型ID
*/ */
private generateArchetypeId(componentTypes: ComponentType[]): ArchetypeId { private generateArchetypeId(componentTypes: ComponentType[]): ArchetypeId {
// 创建缓存键 let entityBits = ComponentTypeManager.instance.getEntityBits(componentTypes);
const cacheKey = componentTypes return entityBits.getValue();
.map(type => getComponentTypeName(type))
.sort()
.join('|');
let archetypeId = this._archetypeIdCache.get(cacheKey);
if (!archetypeId) {
archetypeId = cacheKey;
this._archetypeIdCache.set(cacheKey, archetypeId);
}
return archetypeId;
} }
/** /**
@@ -235,8 +242,15 @@ export class ArchetypeSystem {
componentTypes: [...componentTypes], componentTypes: [...componentTypes],
entities: new Set<Entity>() entities: new Set<Entity>()
}; };
// 存储原型ID - 原型
this._archetypes.set(id, archetype); let archetypeGroup = this._archetypes.get(id.hi);
if (!archetypeGroup) {
archetypeGroup = new Map<number, Archetype>();
this._archetypes.set(id.hi, archetypeGroup);
}
archetypeGroup.set(id.lo, archetype);
// 更新数组
this.updateAllArchetypeArrays();
return archetype; return archetype;
} }

View File

@@ -1,5 +1,6 @@
import type { Component } from '../Component'; import type {Component} from '../Component';
import type { EntitySystem } from '../Systems/EntitySystem'; import type {EntitySystem} from '../Systems';
import {ComponentType} from "../../Types";
/** /**
* 存储组件类型名称的Symbol键 * 存储组件类型名称的Symbol键
@@ -72,8 +73,8 @@ export function ECSSystem(typeName: string) {
* @param componentType 组件构造函数 * @param componentType 组件构造函数
* @returns 组件类型名称 * @returns 组件类型名称
*/ */
export function getComponentTypeName<T extends Component>( export function getComponentTypeName(
componentType: new (...args: any[]) => T componentType: ComponentType
): string { ): string {
// 优先使用装饰器指定的名称 // 优先使用装饰器指定的名称
const decoratorName = (componentType as any)[COMPONENT_TYPE_NAME]; const decoratorName = (componentType as any)[COMPONENT_TYPE_NAME];
@@ -111,7 +112,7 @@ export function getSystemTypeName<T extends EntitySystem>(
* @returns 组件类型名称 * @returns 组件类型名称
*/ */
export function getComponentInstanceTypeName(component: Component): string { export function getComponentInstanceTypeName(component: Component): string {
return getComponentTypeName(component.constructor as new (...args: any[]) => Component); return getComponentTypeName(component.constructor as ComponentType);
} }
/** /**

View File

@@ -1,6 +1,6 @@
import { Component } from '../Component';
import { Bits } from './Bits'; import { Bits } from './Bits';
import { getComponentTypeName } from '../Decorators'; import { getComponentTypeName } from '../Decorators';
import { ComponentType } from "../../Types";
/** /**
* 组件类型管理器 * 组件类型管理器
@@ -29,7 +29,7 @@ export class ComponentTypeManager {
* @param componentType 组件类型构造函数 * @param componentType 组件类型构造函数
* @returns 组件类型ID * @returns 组件类型ID
*/ */
public getTypeId<T extends Component>(componentType: new (...args: unknown[]) => T): number { public getTypeId(componentType: ComponentType): number {
let typeId = this._componentTypes.get(componentType); let typeId = this._componentTypes.get(componentType);
if (typeId === undefined) { if (typeId === undefined) {
@@ -55,7 +55,7 @@ export class ComponentTypeManager {
* @param componentTypes 组件类型构造函数数组 * @param componentTypes 组件类型构造函数数组
* @returns Bits对象 * @returns Bits对象
*/ */
public createBits(...componentTypes: (new (...args: unknown[]) => Component)[]): Bits { public createBits(...componentTypes: ComponentType[]): Bits {
const bits = new Bits(); const bits = new Bits();
for (const componentType of componentTypes) { for (const componentType of componentTypes) {
@@ -71,11 +71,11 @@ export class ComponentTypeManager {
* @param components 组件数组 * @param components 组件数组
* @returns Bits对象 * @returns Bits对象
*/ */
public getEntityBits(components: Component[]): Bits { public getEntityBits(components: ComponentType[]): Bits {
const bits = new Bits(); const bits = new Bits();
for (const component of components) { for (const component of components) {
const typeId = this.getTypeId(component.constructor as new (...args: unknown[]) => Component); const typeId = this.getTypeId(component);
bits.set(typeId); bits.set(typeId);
} }