修复QuerySystem/ArchetypeSystem未响应实体增删Component的问题

This commit is contained in:
YHH
2025-09-28 15:23:59 +08:00
parent 945f772c30
commit 6178851def
6 changed files with 270 additions and 23 deletions

View File

@@ -87,16 +87,64 @@ export class ArchetypeSystem {
public removeEntity(entity: Entity): void {
const archetype = this._entityToArchetype.get(entity);
if (!archetype) return;
const index = archetype.entities.indexOf(entity);
if (index !== -1) {
archetype.entities.splice(index, 1);
archetype.updatedAt = Date.now();
}
this._entityToArchetype.delete(entity);
this.invalidateQueryCache();
}
/**
* 更新实体的原型归属
*
* 当实体的组件组合发生变化时调用此方法,将实体从旧原型移动到新原型。
* 如果新的组件组合对应的原型不存在,将自动创建新原型。
*
* @param entity 要更新的实体
*/
public updateEntity(entity: Entity): void {
const currentArchetype = this._entityToArchetype.get(entity);
const newComponentTypes = this.getEntityComponentTypes(entity);
const newArchetypeId = this.generateArchetypeId(newComponentTypes);
// 如果实体已在正确的原型中,无需更新
if (currentArchetype && currentArchetype.id === newArchetypeId) {
return;
}
// 从旧原型中移除实体
if (currentArchetype) {
const index = currentArchetype.entities.indexOf(entity);
if (index !== -1) {
currentArchetype.entities.splice(index, 1);
currentArchetype.updatedAt = Date.now();
}
}
// 获取或创建新原型
let newArchetype = this._archetypes.get(newArchetypeId);
if (!newArchetype) {
newArchetype = this.createArchetype(newComponentTypes);
}
// 将实体添加到新原型
newArchetype.entities.push(entity);
newArchetype.updatedAt = Date.now();
this._entityToArchetype.set(entity, newArchetype);
// 更新组件索引
if (currentArchetype) {
this.updateComponentIndexes(currentArchetype, currentArchetype.componentTypes, false);
}
this.updateComponentIndexes(newArchetype, newComponentTypes, true);
// 使查询缓存失效
this.invalidateQueryCache();
}
/**
* 查询包含指定组件组合的原型

View File

@@ -229,9 +229,9 @@ export class QuerySystem {
/**
* 从查询系统移除实体
*
*
* 从查询系统中移除指定实体,并清理相关索引。
*
*
* @param entity 要移除的实体
*/
public removeEntity(entity: Entity): void {
@@ -244,12 +244,47 @@ export class QuerySystem {
this.archetypeSystem.removeEntity(entity);
this.clearQueryCache();
// 更新版本号
this._version++;
}
}
/**
* 更新实体在查询系统中的索引
*
* 当实体的组件组合发生变化时调用此方法,高效地更新实体在查询系统中的索引。
*
* @param entity 要更新的实体
*/
public updateEntity(entity: Entity): void {
// 检查实体是否在查询系统中
if (!this.entities.includes(entity)) {
// 如果实体不在系统中,直接添加
this.addEntity(entity);
return;
}
// 先从索引中移除实体的旧状态
this.removeEntityFromIndexes(entity);
// 更新ArchetypeSystem中的实体状态
this.archetypeSystem.updateEntity(entity);
// 更新ComponentIndexManager中的实体状态
this.componentIndexManager.removeEntity(entity);
this.componentIndexManager.addEntity(entity);
// 重新添加实体到索引(基于新的组件状态)
this.addEntityToIndexes(entity);
// 清理查询缓存,因为实体组件状态已改变
this.clearQueryCache();
// 更新版本号以使缓存失效
this._version++;
}
/**
* 将实体添加到各种索引中
*/

View File

@@ -71,6 +71,19 @@ export class Entity {
* 用于发射组件相关事件
*/
public static eventBus: EventBus | null = null;
/**
* 通知Scene中的QuerySystem实体组件发生变动
*
* @param entity 发生组件变动的实体
*/
private static notifyQuerySystems(entity: Entity): void {
// 只通知Scene中的QuerySystem
if (entity.scene && entity.scene.querySystem) {
entity.scene.querySystem.updateEntity(entity);
entity.scene.clearSystemEntityCaches();
}
}
/**
* 实体名称
@@ -369,12 +382,9 @@ export class Entity {
});
}
if (this.scene && this.scene.querySystem) {
this.scene.querySystem.removeEntity(this);
this.scene.querySystem.addEntity(this);
this.scene.clearSystemEntityCaches();
}
// 通知所有相关的QuerySystem组件已变动
Entity.notifyQuerySystems(this);
return component;
}
@@ -521,11 +531,8 @@ export class Entity {
component.entity = null as any;
if (this.scene && this.scene.querySystem) {
this.scene.querySystem.removeEntity(this);
this.scene.querySystem.addEntity(this);
this.scene.clearSystemEntityCaches();
}
// 通知所有相关的QuerySystem组件已变动
Entity.notifyQuerySystems(this);
}
/**
@@ -564,8 +571,11 @@ export class Entity {
component.entity = null as any;
}
this.components.length = 0;
// 通知所有相关的QuerySystem组件已全部移除
Entity.notifyQuerySystems(this);
}
/**

View File

@@ -1,6 +1,6 @@
import { Entity } from '../Entity';
import { PerformanceMonitor } from '../../Utils/PerformanceMonitor';
import { Matcher } from '../Utils/Matcher';
import { Matcher, type QueryCondition } from '../Utils/Matcher';
import type { Scene } from '../Scene';
import type { ISystemBase } from '../../Types';
import type { QuerySystem } from '../Core/QuerySystem';
@@ -274,7 +274,7 @@ export abstract class EntitySystem implements ISystemBase {
/**
* 检查是否为单一条件查询
*/
private isSingleCondition(condition: any): boolean {
private isSingleCondition(condition: QueryCondition): boolean {
const flags =
((condition.all.length > 0) ? 1 : 0) |
((condition.any.length > 0) ? 2 : 0) |
@@ -289,7 +289,7 @@ export abstract class EntitySystem implements ISystemBase {
/**
* 执行单一条件查询
*/
private executeSingleConditionQuery(condition: any, querySystem: any): readonly Entity[] {
private executeSingleConditionQuery(condition: QueryCondition, querySystem: QuerySystem): readonly Entity[] {
// 按标签查询
if (condition.tag !== undefined) {
return querySystem.queryByTag(condition.tag).entities;
@@ -324,7 +324,7 @@ export abstract class EntitySystem implements ISystemBase {
/**
* 执行复合查询
*/
private executeComplexQueryWithIdSets(condition: any, querySystem: QuerySystem): readonly Entity[] {
private executeComplexQueryWithIdSets(condition: QueryCondition, querySystem: QuerySystem): readonly Entity[] {
let resultIds: Set<number> | null = null;
// 1. 应用标签条件作为基础集合
@@ -492,7 +492,7 @@ export abstract class EntitySystem implements ISystemBase {
*
* 使用基于ID集合的单次扫描算法进行复杂查询
*/
private executeComplexQuery(condition: any, querySystem: QuerySystem): readonly Entity[] {
private executeComplexQuery(condition: QueryCondition, querySystem: QuerySystem): readonly Entity[] {
return this.executeComplexQueryWithIdSets(condition, querySystem);
}

View File

@@ -4,7 +4,7 @@ import { getComponentTypeName } from '../Decorators';
/**
* 查询条件类型
*/
interface QueryCondition {
export interface QueryCondition {
all: ComponentType[];
any: ComponentType[];
none: ComponentType[];