空查询应该返回所有实体
This commit is contained in:
@@ -65,8 +65,6 @@ export class ArchetypeSystem {
|
|||||||
|
|
||||||
archetype.entities.add(entity);
|
archetype.entities.add(entity);
|
||||||
this._entityToArchetype.set(entity, archetype);
|
this._entityToArchetype.set(entity, archetype);
|
||||||
|
|
||||||
this.updateComponentIndexes(archetype, componentTypes, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -119,12 +117,6 @@ export class ArchetypeSystem {
|
|||||||
newArchetype.entities.add(entity);
|
newArchetype.entities.add(entity);
|
||||||
this._entityToArchetype.set(entity, newArchetype);
|
this._entityToArchetype.set(entity, newArchetype);
|
||||||
|
|
||||||
// 更新组件索引
|
|
||||||
if (currentArchetype) {
|
|
||||||
this.updateComponentIndexes(currentArchetype, currentArchetype.componentTypes, false);
|
|
||||||
}
|
|
||||||
this.updateComponentIndexes(newArchetype, newComponentTypes, true);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -140,15 +132,48 @@ export class ArchetypeSystem {
|
|||||||
let totalEntities = 0;
|
let totalEntities = 0;
|
||||||
|
|
||||||
if (operation === 'AND') {
|
if (operation === 'AND') {
|
||||||
// 生成查询的 BitMask
|
if (componentTypes.length === 0) {
|
||||||
const queryMask = this.generateArchetypeId(componentTypes);
|
for (const archetype of this._allArchetypes) {
|
||||||
|
|
||||||
// 使用 BitMask 位运算快速判断原型是否包含所有指定组件
|
|
||||||
for (const archetype of this._allArchetypes) {
|
|
||||||
if (BitMask64Utils.hasAll(archetype.id, queryMask)) {
|
|
||||||
matchingArchetypes.push(archetype);
|
matchingArchetypes.push(archetype);
|
||||||
totalEntities += archetype.entities.size;
|
totalEntities += archetype.entities.size;
|
||||||
}
|
}
|
||||||
|
return { archetypes: matchingArchetypes, totalEntities };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (componentTypes.length === 1) {
|
||||||
|
const archetypes = this._componentToArchetypes.get(componentTypes[0]);
|
||||||
|
if (archetypes) {
|
||||||
|
for (const archetype of archetypes) {
|
||||||
|
matchingArchetypes.push(archetype);
|
||||||
|
totalEntities += archetype.entities.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { archetypes: matchingArchetypes, totalEntities };
|
||||||
|
}
|
||||||
|
|
||||||
|
let smallestSet: Set<Archetype> | undefined;
|
||||||
|
let smallestSize = Infinity;
|
||||||
|
|
||||||
|
for (const componentType of componentTypes) {
|
||||||
|
const archetypes = this._componentToArchetypes.get(componentType);
|
||||||
|
if (!archetypes || archetypes.size === 0) {
|
||||||
|
return { archetypes: [], totalEntities: 0 };
|
||||||
|
}
|
||||||
|
if (archetypes.size < smallestSize) {
|
||||||
|
smallestSize = archetypes.size;
|
||||||
|
smallestSet = archetypes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const queryMask = this.generateArchetypeId(componentTypes);
|
||||||
|
|
||||||
|
if (smallestSet) {
|
||||||
|
for (const archetype of smallestSet) {
|
||||||
|
if (BitMask64Utils.hasAll(archetype.id, queryMask)) {
|
||||||
|
matchingArchetypes.push(archetype);
|
||||||
|
totalEntities += archetype.entities.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const foundArchetypes = new Set<Archetype>();
|
const foundArchetypes = new Set<Archetype>();
|
||||||
@@ -258,33 +283,19 @@ export class ArchetypeSystem {
|
|||||||
componentTypes: [...componentTypes],
|
componentTypes: [...componentTypes],
|
||||||
entities: new Set<Entity>()
|
entities: new Set<Entity>()
|
||||||
};
|
};
|
||||||
// 存储原型ID - 原型
|
|
||||||
this._archetypes.set(id,archetype);
|
this._archetypes.set(id,archetype);
|
||||||
// 更新数组
|
|
||||||
this.updateAllArchetypeArrays();
|
this.updateAllArchetypeArrays();
|
||||||
return archetype;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新组件索引
|
|
||||||
*/
|
|
||||||
private updateComponentIndexes(archetype: Archetype, componentTypes: ComponentType[], add: boolean): void {
|
|
||||||
for (const componentType of componentTypes) {
|
for (const componentType of componentTypes) {
|
||||||
let archetypes = this._componentToArchetypes.get(componentType);
|
let archetypes = this._componentToArchetypes.get(componentType);
|
||||||
if (!archetypes) {
|
if (!archetypes) {
|
||||||
archetypes = new Set();
|
archetypes = new Set();
|
||||||
this._componentToArchetypes.set(componentType, archetypes);
|
this._componentToArchetypes.set(componentType, archetypes);
|
||||||
}
|
}
|
||||||
|
archetypes.add(archetype);
|
||||||
if (add) {
|
|
||||||
archetypes.add(archetype);
|
|
||||||
} else {
|
|
||||||
archetypes.delete(archetype);
|
|
||||||
if (archetypes.size === 0) {
|
|
||||||
this._componentToArchetypes.delete(componentType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return archetype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -77,19 +77,16 @@ export class QuerySystem {
|
|||||||
private entities: Entity[] = [];
|
private entities: Entity[] = [];
|
||||||
private entityIndex: EntityIndex;
|
private entityIndex: EntityIndex;
|
||||||
|
|
||||||
// 版本号,用于缓存失效
|
|
||||||
private _version = 0;
|
private _version = 0;
|
||||||
|
|
||||||
// 查询缓存系统
|
|
||||||
private queryCache = new Map<string, QueryCacheEntry>();
|
private queryCache = new Map<string, QueryCacheEntry>();
|
||||||
private cacheMaxSize = 1000;
|
private cacheMaxSize = 1000;
|
||||||
private cacheTimeout = 5000; // 5秒缓存过期
|
private cacheTimeout = 5000;
|
||||||
|
|
||||||
private componentMaskCache = new Map<string, BitMask64Data>();
|
private componentMaskCache = new Map<string, BitMask64Data>();
|
||||||
|
|
||||||
private archetypeSystem: ArchetypeSystem;
|
private archetypeSystem: ArchetypeSystem;
|
||||||
|
|
||||||
// 性能统计
|
|
||||||
private queryStats = {
|
private queryStats = {
|
||||||
totalQueries: 0,
|
totalQueries: 0,
|
||||||
cacheHits: 0,
|
cacheHits: 0,
|
||||||
@@ -99,6 +96,9 @@ export class QuerySystem {
|
|||||||
dirtyChecks: 0
|
dirtyChecks: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private resultArrayPool: Entity[][] = [];
|
||||||
|
private poolMaxSize = 50;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.entityIndex = {
|
this.entityIndex = {
|
||||||
byTag: new Map(),
|
byTag: new Map(),
|
||||||
@@ -108,7 +108,19 @@ export class QuerySystem {
|
|||||||
this.archetypeSystem = new ArchetypeSystem();
|
this.archetypeSystem = new ArchetypeSystem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private acquireResultArray(): Entity[] {
|
||||||
|
if (this.resultArrayPool.length > 0) {
|
||||||
|
return this.resultArrayPool.pop()!;
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
private releaseResultArray(array: Entity[]): void {
|
||||||
|
if (this.resultArrayPool.length < this.poolMaxSize) {
|
||||||
|
array.length = 0;
|
||||||
|
this.resultArrayPool.push(array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置实体列表并重建索引
|
* 设置实体列表并重建索引
|
||||||
@@ -459,18 +471,21 @@ export class QuerySystem {
|
|||||||
this.queryStats.archetypeHits++;
|
this.queryStats.archetypeHits++;
|
||||||
const archetypeResult = this.archetypeSystem.queryArchetypes(componentTypes, 'OR');
|
const archetypeResult = this.archetypeSystem.queryArchetypes(componentTypes, 'OR');
|
||||||
|
|
||||||
const entities: Entity[] = [];
|
const entities = this.acquireResultArray();
|
||||||
for (const archetype of archetypeResult.archetypes) {
|
for (const archetype of archetypeResult.archetypes) {
|
||||||
for (const entity of archetype.entities) {
|
for (const entity of archetype.entities) {
|
||||||
entities.push(entity);
|
entities.push(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.addToCache(cacheKey, entities);
|
const frozenEntities = [...entities];
|
||||||
|
this.releaseResultArray(entities);
|
||||||
|
|
||||||
|
this.addToCache(cacheKey, frozenEntities);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
entities,
|
entities: frozenEntities,
|
||||||
count: entities.length,
|
count: frozenEntities.length,
|
||||||
executionTime: performance.now() - startTime,
|
executionTime: performance.now() - startTime,
|
||||||
fromCache: false
|
fromCache: false
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -529,10 +529,6 @@ describe('Scene - 场景管理系统测试', () => {
|
|||||||
expect(velocityResult.entities.length).toBe(entityCount / 2);
|
expect(velocityResult.entities.length).toBe(entityCount / 2);
|
||||||
expect(healthResult.entities.length).toBe(Math.floor(entityCount / 3) + 1);
|
expect(healthResult.entities.length).toBe(Math.floor(entityCount / 3) + 1);
|
||||||
|
|
||||||
// 性能断言(这些值可能需要根据实际环境调整)
|
|
||||||
// 性能记录:场景创建性能数据,不设硬阈值避免CI不稳定
|
|
||||||
// 性能记录:场景查询性能数据,不设硬阈值避免CI不稳定
|
|
||||||
|
|
||||||
console.log(`创建${entityCount}个实体耗时: ${creationTime.toFixed(2)}ms`);
|
console.log(`创建${entityCount}个实体耗时: ${creationTime.toFixed(2)}ms`);
|
||||||
console.log(`查询操作耗时: ${queryTime.toFixed(2)}ms`);
|
console.log(`查询操作耗时: ${queryTime.toFixed(2)}ms`);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user