2025-06-07 20:32:43 +08:00
|
|
|
import { Entity } from '../Entity';
|
|
|
|
|
import { Component } from '../Component';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 高性能实体列表管理器
|
|
|
|
|
* 管理场景中的所有实体,支持快速查找和批量操作
|
|
|
|
|
*/
|
|
|
|
|
export class EntityList {
|
|
|
|
|
public buffer: Entity[] = [];
|
|
|
|
|
private _scene: any; // 临时使用any,避免循环依赖
|
|
|
|
|
|
|
|
|
|
// 索引映射,提升查找性能
|
|
|
|
|
private _idToEntity = new Map<number, Entity>();
|
|
|
|
|
private _nameToEntities = new Map<string, Entity[]>();
|
|
|
|
|
|
|
|
|
|
// 延迟操作队列
|
|
|
|
|
private _entitiesToAdd: Entity[] = [];
|
|
|
|
|
private _entitiesToRemove: Entity[] = [];
|
|
|
|
|
private _isUpdating = false;
|
|
|
|
|
|
|
|
|
|
public get count(): number {
|
|
|
|
|
return this.buffer.length;
|
|
|
|
|
}
|
2020-06-08 20:11:58 +08:00
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
constructor(scene: any) {
|
|
|
|
|
this._scene = scene;
|
|
|
|
|
}
|
2020-07-24 15:29:07 +08:00
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
/**
|
|
|
|
|
* 添加实体(立即添加或延迟添加)
|
|
|
|
|
* @param entity 要添加的实体
|
|
|
|
|
*/
|
|
|
|
|
public add(entity: Entity): void {
|
|
|
|
|
if (this._isUpdating) {
|
|
|
|
|
// 如果正在更新中,延迟添加
|
|
|
|
|
this._entitiesToAdd.push(entity);
|
|
|
|
|
} else {
|
|
|
|
|
this.addImmediate(entity);
|
2020-07-24 15:29:07 +08:00
|
|
|
}
|
2025-06-07 20:32:43 +08:00
|
|
|
}
|
2020-07-24 15:29:07 +08:00
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
/**
|
|
|
|
|
* 立即添加实体
|
|
|
|
|
* @param entity 要添加的实体
|
|
|
|
|
*/
|
|
|
|
|
private addImmediate(entity: Entity): void {
|
|
|
|
|
// 检查是否已存在
|
|
|
|
|
if (this._idToEntity.has(entity.id)) {
|
|
|
|
|
return;
|
2020-06-08 20:11:58 +08:00
|
|
|
}
|
|
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
this.buffer.push(entity);
|
|
|
|
|
this._idToEntity.set(entity.id, entity);
|
|
|
|
|
|
|
|
|
|
// 更新名称索引
|
|
|
|
|
this.updateNameIndex(entity, true);
|
|
|
|
|
}
|
2020-06-08 20:11:58 +08:00
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
/**
|
|
|
|
|
* 移除实体(立即移除或延迟移除)
|
|
|
|
|
* @param entity 要移除的实体
|
|
|
|
|
*/
|
|
|
|
|
public remove(entity: Entity): void {
|
|
|
|
|
if (this._isUpdating) {
|
|
|
|
|
// 如果正在更新中,延迟移除
|
|
|
|
|
this._entitiesToRemove.push(entity);
|
|
|
|
|
} else {
|
|
|
|
|
this.removeImmediate(entity);
|
2020-06-08 20:11:58 +08:00
|
|
|
}
|
2025-06-07 20:32:43 +08:00
|
|
|
}
|
2020-06-08 20:11:58 +08:00
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
/**
|
|
|
|
|
* 立即移除实体
|
|
|
|
|
* @param entity 要移除的实体
|
|
|
|
|
*/
|
|
|
|
|
private removeImmediate(entity: Entity): void {
|
|
|
|
|
const index = this.buffer.indexOf(entity);
|
|
|
|
|
if (index !== -1) {
|
|
|
|
|
this.buffer.splice(index, 1);
|
|
|
|
|
this._idToEntity.delete(entity.id);
|
|
|
|
|
|
|
|
|
|
// 更新名称索引
|
|
|
|
|
this.updateNameIndex(entity, false);
|
2020-07-22 20:07:14 +08:00
|
|
|
}
|
2025-06-07 20:32:43 +08:00
|
|
|
}
|
2020-06-08 20:11:58 +08:00
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
/**
|
|
|
|
|
* 移除所有实体
|
|
|
|
|
*/
|
|
|
|
|
public removeAllEntities(): void {
|
|
|
|
|
for (let i = this.buffer.length - 1; i >= 0; i--) {
|
|
|
|
|
this.buffer[i].destroy();
|
2020-06-08 20:11:58 +08:00
|
|
|
}
|
2025-06-07 20:32:43 +08:00
|
|
|
|
|
|
|
|
this.buffer.length = 0;
|
|
|
|
|
this._idToEntity.clear();
|
|
|
|
|
this._nameToEntities.clear();
|
|
|
|
|
this._entitiesToAdd.length = 0;
|
|
|
|
|
this._entitiesToRemove.length = 0;
|
|
|
|
|
}
|
2020-06-08 20:11:58 +08:00
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
/**
|
|
|
|
|
* 更新实体列表,处理延迟操作
|
|
|
|
|
*/
|
|
|
|
|
public updateLists(): void {
|
|
|
|
|
// 处理延迟添加的实体
|
|
|
|
|
if (this._entitiesToAdd.length > 0) {
|
|
|
|
|
for (const entity of this._entitiesToAdd) {
|
|
|
|
|
this.addImmediate(entity);
|
2020-07-22 20:07:14 +08:00
|
|
|
}
|
2025-06-07 20:32:43 +08:00
|
|
|
this._entitiesToAdd.length = 0;
|
2020-07-22 20:07:14 +08:00
|
|
|
}
|
2020-06-08 20:11:58 +08:00
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
// 处理延迟移除的实体
|
|
|
|
|
if (this._entitiesToRemove.length > 0) {
|
|
|
|
|
for (const entity of this._entitiesToRemove) {
|
|
|
|
|
this.removeImmediate(entity);
|
2023-03-13 23:32:24 +08:00
|
|
|
}
|
2025-06-07 20:32:43 +08:00
|
|
|
this._entitiesToRemove.length = 0;
|
2020-06-08 20:11:58 +08:00
|
|
|
}
|
2025-06-07 20:32:43 +08:00
|
|
|
}
|
2020-06-08 20:11:58 +08:00
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
/**
|
|
|
|
|
* 更新所有实体
|
|
|
|
|
*/
|
|
|
|
|
public update(): void {
|
|
|
|
|
this._isUpdating = true;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
for (let i = 0; i < this.buffer.length; i++) {
|
|
|
|
|
const entity = this.buffer[i];
|
|
|
|
|
if (entity.enabled && !entity.isDestroyed) {
|
2020-07-22 20:07:14 +08:00
|
|
|
entity.update();
|
2023-03-13 23:32:24 +08:00
|
|
|
}
|
2020-07-22 20:07:14 +08:00
|
|
|
}
|
2025-06-07 20:32:43 +08:00
|
|
|
} finally {
|
|
|
|
|
this._isUpdating = false;
|
2020-07-22 20:07:14 +08:00
|
|
|
}
|
2025-06-07 20:32:43 +08:00
|
|
|
|
|
|
|
|
// 处理延迟操作
|
|
|
|
|
this.updateLists();
|
|
|
|
|
}
|
2020-06-08 20:11:58 +08:00
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
/**
|
|
|
|
|
* 根据名称查找实体(使用索引,O(1)复杂度)
|
|
|
|
|
* @param name 实体名称
|
|
|
|
|
* @returns 找到的第一个实体或null
|
|
|
|
|
*/
|
|
|
|
|
public findEntity(name: string): Entity | null {
|
|
|
|
|
const entities = this._nameToEntities.get(name);
|
|
|
|
|
return entities && entities.length > 0 ? entities[0] : null;
|
|
|
|
|
}
|
2023-03-13 23:32:24 +08:00
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
/**
|
|
|
|
|
* 根据名称查找所有实体
|
|
|
|
|
* @param name 实体名称
|
|
|
|
|
* @returns 找到的所有实体数组
|
|
|
|
|
*/
|
|
|
|
|
public findEntitiesByName(name: string): Entity[] {
|
|
|
|
|
return this._nameToEntities.get(name) || [];
|
|
|
|
|
}
|
2023-03-13 23:32:24 +08:00
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
/**
|
|
|
|
|
* 根据ID查找实体(使用索引,O(1)复杂度)
|
|
|
|
|
* @param id 实体ID
|
|
|
|
|
* @returns 找到的实体或null
|
|
|
|
|
*/
|
|
|
|
|
public findEntityById(id: number): Entity | null {
|
|
|
|
|
return this._idToEntity.get(id) || null;
|
|
|
|
|
}
|
2020-07-24 15:29:07 +08:00
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
/**
|
|
|
|
|
* 根据标签查找实体
|
|
|
|
|
* @param tag 标签
|
|
|
|
|
* @returns 找到的所有实体数组
|
|
|
|
|
*/
|
|
|
|
|
public findEntitiesByTag(tag: number): Entity[] {
|
|
|
|
|
const result: Entity[] = [];
|
|
|
|
|
|
|
|
|
|
for (const entity of this.buffer) {
|
|
|
|
|
if (entity.tag === tag) {
|
|
|
|
|
result.push(entity);
|
2020-07-22 20:07:14 +08:00
|
|
|
}
|
2020-06-09 22:32:18 +08:00
|
|
|
}
|
2025-06-07 20:32:43 +08:00
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2020-07-24 15:29:07 +08:00
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
/**
|
|
|
|
|
* 根据组件类型查找实体
|
|
|
|
|
* @param componentType 组件类型
|
|
|
|
|
* @returns 找到的所有实体数组
|
|
|
|
|
*/
|
|
|
|
|
public findEntitiesWithComponent<T extends Component>(componentType: new (...args: any[]) => T): Entity[] {
|
|
|
|
|
const result: Entity[] = [];
|
|
|
|
|
|
|
|
|
|
for (const entity of this.buffer) {
|
|
|
|
|
if (entity.hasComponent(componentType)) {
|
|
|
|
|
result.push(entity);
|
2020-11-26 20:02:53 +08:00
|
|
|
}
|
2020-07-24 15:29:07 +08:00
|
|
|
}
|
2025-06-07 20:32:43 +08:00
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2020-07-24 15:29:07 +08:00
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
/**
|
|
|
|
|
* 批量操作:对所有实体执行指定操作
|
|
|
|
|
* @param action 要执行的操作
|
|
|
|
|
*/
|
|
|
|
|
public forEach(action: (entity: Entity) => void): void {
|
|
|
|
|
for (const entity of this.buffer) {
|
|
|
|
|
action(entity);
|
2021-04-26 15:23:16 +08:00
|
|
|
}
|
2025-06-07 20:32:43 +08:00
|
|
|
}
|
2021-04-26 15:23:16 +08:00
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
/**
|
|
|
|
|
* 批量操作:对符合条件的实体执行指定操作
|
|
|
|
|
* @param predicate 筛选条件
|
|
|
|
|
* @param action 要执行的操作
|
|
|
|
|
*/
|
|
|
|
|
public forEachWhere(predicate: (entity: Entity) => boolean, action: (entity: Entity) => void): void {
|
|
|
|
|
for (const entity of this.buffer) {
|
|
|
|
|
if (predicate(entity)) {
|
|
|
|
|
action(entity);
|
2021-02-01 11:11:53 +08:00
|
|
|
}
|
2020-07-24 15:29:07 +08:00
|
|
|
}
|
2025-06-07 20:32:43 +08:00
|
|
|
}
|
2020-07-24 15:29:07 +08:00
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
/**
|
|
|
|
|
* 更新名称索引
|
|
|
|
|
* @param entity 实体
|
|
|
|
|
* @param isAdd 是否为添加操作
|
|
|
|
|
*/
|
|
|
|
|
private updateNameIndex(entity: Entity, isAdd: boolean): void {
|
|
|
|
|
if (!entity.name) {
|
|
|
|
|
return;
|
2021-03-30 18:02:27 +08:00
|
|
|
}
|
|
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
if (isAdd) {
|
|
|
|
|
let entities = this._nameToEntities.get(entity.name);
|
|
|
|
|
if (!entities) {
|
|
|
|
|
entities = [];
|
|
|
|
|
this._nameToEntities.set(entity.name, entities);
|
2020-07-24 15:29:07 +08:00
|
|
|
}
|
2025-06-07 20:32:43 +08:00
|
|
|
entities.push(entity);
|
|
|
|
|
} else {
|
|
|
|
|
const entities = this._nameToEntities.get(entity.name);
|
|
|
|
|
if (entities) {
|
|
|
|
|
const index = entities.indexOf(entity);
|
|
|
|
|
if (index !== -1) {
|
|
|
|
|
entities.splice(index, 1);
|
|
|
|
|
|
|
|
|
|
// 如果数组为空,删除映射
|
|
|
|
|
if (entities.length === 0) {
|
|
|
|
|
this._nameToEntities.delete(entity.name);
|
2021-05-13 16:58:24 +08:00
|
|
|
}
|
2020-07-24 15:29:07 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-06-07 20:32:43 +08:00
|
|
|
}
|
2021-03-26 17:36:50 +08:00
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
/**
|
|
|
|
|
* 获取实体列表的统计信息
|
|
|
|
|
* @returns 统计信息
|
|
|
|
|
*/
|
|
|
|
|
public getStats(): {
|
|
|
|
|
totalEntities: number;
|
|
|
|
|
activeEntities: number;
|
|
|
|
|
pendingAdd: number;
|
|
|
|
|
pendingRemove: number;
|
|
|
|
|
nameIndexSize: number;
|
|
|
|
|
} {
|
|
|
|
|
let activeCount = 0;
|
|
|
|
|
for (const entity of this.buffer) {
|
|
|
|
|
if (entity.enabled && !entity.isDestroyed) {
|
|
|
|
|
activeCount++;
|
2021-03-26 17:36:50 +08:00
|
|
|
}
|
|
|
|
|
}
|
2023-03-13 23:32:24 +08:00
|
|
|
|
2025-06-07 20:32:43 +08:00
|
|
|
return {
|
|
|
|
|
totalEntities: this.buffer.length,
|
|
|
|
|
activeEntities: activeCount,
|
|
|
|
|
pendingAdd: this._entitiesToAdd.length,
|
|
|
|
|
pendingRemove: this._entitiesToRemove.length,
|
|
|
|
|
nameIndexSize: this._nameToEntities.size
|
|
|
|
|
};
|
2020-06-08 20:11:58 +08:00
|
|
|
}
|
2020-07-22 20:07:14 +08:00
|
|
|
}
|