1. 明确文档说明isRecycle=false的使用场景

2. 提供清理缓存的API
This commit is contained in:
dgflash
2026-03-08 12:46:52 +08:00
parent 9d65c31016
commit 2c95d13b9e

View File

@@ -105,10 +105,25 @@ export class ECSEntity {
private mask: ECSMask = new ECSMask();
/** 当前实体身上附加的组件构造函数 */
private compTid2Ctor: Map<number, CompType<ecs.IComp>> = new Map();
/** 配合 entity.remove(Comp, false) 记录组件实例上的缓存数据,在添加时恢复原数据 */
/**
* 配合 entity.remove(Comp, false) 记录组件实例上的缓存数据,在添加时恢复原数据
*
* ⚠️ 核心机制:
* - isRecycle=true调用reset()根据canRecycle决定是否回收到全局池
* - isRecycle=false不调用reset(),缓存在实体上
*
* ⚠️ 使用场景说明:
* 1. UI显示/隐藏 - 保留UI状态数据
* 2. 技能冷却 - 保留冷却时间
* 3. 临时禁用功能 - 保留配置数据
*
* 💡 管理建议:
* - 无任何限制,完全由用户自行管理
* - 使用 ECSMemoryMonitor 监控缓存使用情况
* - 定期调用 clearComponentCache() 或 clearAllComponentCache() 清理
* - 在场景切换、内存警告时主动清理缓存
*/
private compTid2Obj: Map<number, ecs.IComp> = new Map();
/** 组件缓存容量限制,防止内存泄漏 */
private static readonly MAX_CACHE_COMP = 10;
/** 获取 mask 对象(内部使用) */
getMask(): ECSMask {
@@ -286,9 +301,29 @@ export class ECSEntity {
/**
* 从实体上删除指定组件
* @param ctor 组件构造函数或者组件Tag
* @param isRecycle 是否回收该组件对象。对于有些组件上有大量数据,当要描述移除组件但是不想清除组件上的数据是可以
* 设置该参数为false这样该组件对象会缓存在实体身上下次重新添加组件时会将该组件对象添加回来不会重新从组件缓存
* 池中拿一个组件来用。
* @param isRecycle 是否回收该组件对象
*
* **isRecycle=true默认**
* - 调用组件的 reset() 方法清理数据
* - 如果 canRecycle=true回收到全局对象池供复用
* - 如果 canRecycle=false直接销毁
* - 适用于大部分场景
*
* **isRecycle=false**
* - 不调用 reset(),数据完整保留
* - 组件缓存在当前实体上,下次 add() 时恢复
* - 无任何限制和检查,完全由用户自行管理
* - 适用于需要保留状态的场景UI切换、技能冷却等
*
* ⚠️ isRecycle=false 使用场景:
* - UI显示/隐藏保留UI状态如滚动位置、选中项
* - 技能冷却:保留冷却剩余时间
* - 临时禁用:保留配置数据,稍后恢复
*
* 💡 管理建议:
* - 使用 ECSMemoryMonitor 监控缓存使用情况
* - 定期调用 clearComponentCache() 或 clearAllComponentCache() 清理
* - 在场景切换、内存警告时主动清理缓存
*/
remove(ctor: CompType<ecs.IComp>, isRecycle = true): void {
const componentTypeId = typeof ctor === 'number' ? ctor : ctor.tid;
@@ -307,8 +342,8 @@ export class ECSEntity {
if (isRecycle) {
comp.reset();
// 使用动态池管理器回收组件
// 回收到全局池
if (comp.canRecycle) {
const ctor = ECSModel.compCtors[componentTypeId];
if (ctor) {
@@ -322,26 +357,9 @@ export class ECSEntity {
}
}
else {
// 限制缓存组件数量,防止内存泄漏
if (this.compTid2Obj.size < ECSEntity.MAX_CACHE_COMP) {
this.compTid2Obj.set(componentTypeId, comp); // 用于缓存显示对象组件
}
else {
// 超过限制,强制回收
console.warn(`实体 ${this.name} 缓存组件数量超过限制,强制回收组件 ${compName}`);
comp.reset();
if (comp.canRecycle) {
const ctor = ECSModel.compCtors[componentTypeId];
if (ctor) {
const pool = globalPoolCoordinator.getPool(
ctor.compName,
() => new (ctor as any)(),
ctor
);
pool.recycle(comp);
}
}
}
// isRecycle=false用户明确要求缓存完全尊重用户意图
// 不做任何检查和限制,由用户通过 ECSMemoryMonitor 自行管理
this.compTid2Obj.set(componentTypeId, comp);
}
// 删除实体上的组件逻辑
@@ -350,6 +368,78 @@ export class ECSEntity {
this.compTid2Ctor.delete(componentTypeId);
broadcastCompAddOrRemove(this, componentTypeId);
}
/**
* 清理指定组件的缓存
* @param ctor 组件构造函数
*/
clearComponentCache(ctor: CompType<ecs.IComp>): void {
const componentTypeId = typeof ctor === 'number' ? ctor : ctor.tid;
const comp = this.compTid2Obj.get(componentTypeId);
if (comp) {
this.compTid2Obj.delete(componentTypeId);
const ctorObj = ECSModel.compCtors[componentTypeId];
const compName = ctorObj?.compName || `tid:${componentTypeId}`;
comp.reset();
if (comp.canRecycle) {
if (ctorObj) {
const pool = globalPoolCoordinator.getPool(
ctorObj.compName,
() => new (ctorObj as any)(),
ctorObj
);
pool.recycle(comp);
}
}
console.log(`[ECS] 实体 ${this.name} 清理组件缓存: ${compName}`);
}
}
/**
* 清理所有组件缓存
*/
clearAllComponentCache(): void {
if (this.compTid2Obj.size === 0) return;
const count = this.compTid2Obj.size;
this.compTid2Obj.forEach((comp, tid) => {
comp.reset();
if (comp.canRecycle) {
const ctor = ECSModel.compCtors[tid];
if (ctor) {
const pool = globalPoolCoordinator.getPool(
ctor.compName,
() => new (ctor as any)(),
ctor
);
pool.recycle(comp);
}
}
});
this.compTid2Obj.clear();
console.log(`[ECS] 实体 ${this.name} 清理所有缓存,共 ${count} 个组件`);
}
/**
* 获取缓存的组件数量
*/
getCachedComponentCount(): number {
return this.compTid2Obj.size;
}
/**
* 获取缓存的组件列表(用于监控)
*/
getCachedComponents(): Map<number, ecs.IComp> {
return new Map(this.compTid2Obj);
}
/** 销毁实体,实体会被回收到实体缓存池中 */
destroy(): void {
@@ -375,7 +465,7 @@ export class ECSEntity {
destroyEntity(this);
// 清理缓存的组件对象,防止内存泄漏
this.compTid2Obj.clear();
this.clearAllComponentCache();
}
private _remove(comp: CompType<ecs.IComp>): void {