diff --git a/Runtime/ABase/GameObjectPool/fe.md b/Runtime/ABase/GameObjectPool/fe.md deleted file mode 100644 index 0c7f3dd..0000000 --- a/Runtime/ABase/GameObjectPool/fe.md +++ /dev/null @@ -1,722 +0,0 @@ -# GameObjectPool 最优架构设计文档 - -## 1. 文档目标 - -本文档定义 `GameObjectPool` 模块的目标形态,用于支撑游戏内所有 `GameObject` 相关对象的统一池化,包括但不限于: - -- 怪物 / NPC -- 子弹 / 投射物 -- 特效 / 粒子 / VFXGraph -- 掉落物 / 临时交互物 -- 飘字 / World UI -- 音效壳对象 -- 可复用的场景装饰物 - -目标不是做一个“能复用 prefab 的基础对象池”,而是做一个“可覆盖全项目高频对象生命周期管理”的统一池化体系。 - ---- - -## 2. 现状结论 - -当前实现可以作为基础版对象池使用,但不是最优方案,主要原因如下: - -- 只处理 `SetActive`、`SetParent`、Transform 复位,不具备统一的业务状态重置协议 -- 池满时只会返回 `null`,没有按对象类型区分溢出策略 -- 预热只支持静态固定值,不支持场景级、战斗级、波次级预热 -- 淘汰策略只基于时间,不包含优先级、预算、低内存策略 -- 清理调度依赖全量扫描,不适合大量池并存 -- 配置维度不足,无法精细支撑怪物、特效、子弹等不同对象类型 -- 缺少自动回收能力 -- 缺少运行时统计闭环,无法逼近最优容量配置 - -结论: - -- 当前实现可以继续作为底层雏形 -- 不建议直接扩写成最终方案 -- 最优方向应升级为“分层池化架构” - ---- - -## 3. 设计目标 - -### 3.1 功能目标 - -- 统一管理所有 `GameObject` 池化对象 -- 支持同步获取、异步获取、预热、回收、自动回收 -- 支持对象在复用前后执行自定义重置 -- 支持按对象类型定义不同的容量与淘汰策略 -- 支持运行时统计与调优建议导出 -- 支持低内存场景下的激进回收 - -### 3.2 性能目标 - -- 高频借还路径保持 O(1) 或近似 O(1) -- 避免重复加载同一 prefab -- 避免单帧大量 Instantiate / Destroy -- 清理与预热都采用预算驱动,而不是无上限循环 -- 复杂对象允许使用轻量休眠,而非强制全量 `SetActive` - -### 3.3 工程目标 - -- 配置清晰,可由策划 / TA / 程序共同维护 -- 业务接入方式统一,不让每个系统各自发明对象池 -- 支持逐步迁移,兼容现有 `GameObjectPoolManager` - ---- - -## 4. 总体架构 - -推荐采用三层结构。 - -### 4.1 第一层:Prefab 池层 - -职责: - -- prefab 资源加载与引用持有 -- 单 prefab 实例池管理 -- 容量控制 -- 预热 -- 淘汰 -- 调度 - -建议保留当前 `RuntimePrefabPool` 的职责方向,但增强其策略能力。 - -### 4.2 第二层:实例生命周期层 - -职责: - -- 统一对象创建后初始化 -- 对象借出前重置 -- 对象归还前清理 -- 对象销毁前释放内部资源 -- 管理自动回收与上下文注入 - -该层是当前模块最缺失的部分,也是怪物、子弹、特效能够统一纳入池化的关键。 - -### 4.3 第三层:业务门面层 - -职责: - -- 向业务提供强类型 API -- 隐藏字符串路径、组名、预热细节 -- 承载特定对象的默认策略 - -示例: - -```csharp -Enemy enemy = enemyPool.Spawn(enemyId, spawnContext); -Bullet bullet = bulletPool.Spawn(bulletConfigId, spawnContext); -FxHandle fx = fxPool.Play(fxId, position, rotation, autoRecycle: true); -``` - -不建议把字符串 `assetPath` 作为业务层唯一入口。 -字符串路径池应作为底层资源定位方式,而不是最终业务接口。 - ---- - -## 5. 生命周期协议设计 - -统一池化必须提供明确的生命周期协议。 - -### 5.1 核心接口 - -```csharp -public interface IGameObjectPoolable -{ - void OnPoolCreate(); - void OnPoolGet(in PoolSpawnContext context); - void OnPoolRelease(); - void OnPoolDestroy(); -} -``` - -语义建议: - -- `OnPoolCreate` - 仅在实例第一次创建后调用一次 -- `OnPoolGet` - 每次借出时调用,用于注入上下文、重置运行态 -- `OnPoolRelease` - 每次归还时调用,用于停止逻辑、清理状态 -- `OnPoolDestroy` - 实例真正销毁前调用,用于释放自持资源 - -### 5.2 可选扩展接口 - -```csharp -public interface IPoolAutoRecycle -{ - bool TryGetAutoRecycleDelay(out float delaySeconds); -} - -public interface IPoolResettablePhysics -{ - void ResetPhysicsState(); -} - -public interface IPoolResettableVisual -{ - void ResetVisualState(); -} - -public interface IPoolResettableAnimation -{ - void ResetAnimationState(); -} - -public interface IPoolSleepable -{ - void EnterSleep(); - void ExitSleep(in PoolSpawnContext context); -} -``` - -说明: - -- `IPoolSleepable` 主要给怪物 / NPC 这类重对象使用 -- `IPoolResettablePhysics` 适合子弹、投射物、掉落物 -- `IPoolResettableVisual` 适合特效、Trail、VFXGraph、Renderer 状态清理 - -### 5.3 PoolSpawnContext - -`OnPoolGet` 需要统一上下文,避免靠外部脚本到处手动赋值。 - -建议结构: - -```csharp -public readonly struct PoolSpawnContext -{ - public readonly string AssetPath; - public readonly string Group; - public readonly Transform Parent; - public readonly Vector3 Position; - public readonly Quaternion Rotation; - public readonly object UserData; - public readonly int OwnerId; - public readonly int TeamId; - public readonly uint SpawnFrame; -} -``` - -说明: - -- `UserData` 用于挂通用扩展参数 -- 高频场景可以进一步拆成强类型上下文 - ---- - -## 6. 池实例状态机 - -每个实例建议具备明确状态: - -- `Uninitialized` -- `Inactive` -- `Active` -- `Releasing` -- `Destroying` - -状态转换: - -```text -Create -> Inactive -> Active -> Releasing -> Inactive -Create -> Inactive -> Destroying -> Destroy -Active -> Destroying -> Destroy -``` - -价值: - -- 避免重复回收 -- 避免回收中再次借出 -- 便于统计与调试 -- 便于做自动回收与异步保护 - ---- - -## 7. 配置模型设计 - -当前 `PoolConfig` 维度不够,建议升级为两层配置: - -- `PoolProfile` -- `PoolRule` - -### 7.1 PoolProfile - -定义一类对象的默认策略,例如: - -- `BulletProfile` -- `FxProfile` -- `EnemyProfile` -- `UiWorldProfile` - -示例字段: - -```csharp -public sealed class PoolProfile -{ - public string profileName; - public PoolObjectKind objectKind; - public PoolOverflowPolicy overflowPolicy; - public PoolTrimPolicy trimPolicy; - public PoolActivationMode activationMode; - public PoolResetMode resetMode; - - public int minRetained; - public int softCapacity; - public int hardCapacity; - - public float idleTrimDelay; - public float prefabUnloadDelay; - public float autoRecycleDelay; - - public int trimBatchPerTick; - public int warmupBatchPerFrame; - public float warmupFrameBudgetMs; - - public bool allowRuntimeExpand; - public bool preloadOnInitialize; - public bool keepPrefabResident; - public bool aggressiveTrimOnLowMemory; -} -``` - -### 7.2 PoolRule - -定义具体资源命中规则。 - -```csharp -public sealed class PoolRule -{ - public string group; - public string assetPath; - public PoolMatchMode matchMode; - public PoolResourceLoaderType loaderType; - public string profileName; - - public bool overrideCapacity; - public int minRetained; - public int softCapacity; - public int hardCapacity; - - public bool overridePrewarm; - public int prewarmCount; - public PoolPrewarmPhase prewarmPhase; - - public int priority; -} -``` - -设计原则: - -- `Profile` 管类型策略 -- `Rule` 管具体命中 -- 高频热点对象优先使用 `Exact` -- `Prefix` 只做默认兜底 - ---- - -## 8. 核心枚举草案 - -### 8.1 对象类型 - -```csharp -public enum PoolObjectKind -{ - Default = 0, - Bullet = 1, - Effect = 2, - Enemy = 3, - Npc = 4, - Pickup = 5, - WorldUi = 6, - AudioProxy = 7, - SceneProp = 8 -} -``` - -### 8.2 池满策略 - -```csharp -public enum PoolOverflowPolicy -{ - FailFast = 0, - InstantiateOneShot = 1, - AutoExpand = 2, - RecycleOldestInactive = 3, - DropNewestRequest = 4 -} -``` - -### 8.3 清理策略 - -```csharp -public enum PoolTrimPolicy -{ - None = 0, - IdleOnly = 1, - IdleAndPriority = 2, - AggressiveOnLowMemory = 3 -} -``` - -### 8.4 激活模式 - -```csharp -public enum PoolActivationMode -{ - SetActive = 0, - SleepWake = 1, - Custom = 2 -} -``` - -### 8.5 重置模式 - -```csharp -public enum PoolResetMode -{ - TransformOnly = 0, - PoolableCallbacks = 1, - FullReset = 2, - Custom = 3 -} -``` - -### 8.6 预热阶段 - -```csharp -public enum PoolPrewarmPhase -{ - None = 0, - AppInitialize = 1, - SceneLoad = 2, - BattlePrepare = 3, - WavePrepare = 4, - OnDemand = 5 -} -``` - ---- - -## 9. 不同对象类型的推荐策略 - -### 9.1 子弹 - -建议: - -- `softCapacity` 较高 -- `hardCapacity` 可比 `softCapacity` 高 1.5 到 2 倍 -- 默认支持 `AutoExpand` 或 `InstantiateOneShot` -- 必须支持自动回收 -- 必须清理 `Rigidbody / Collider / TrailRenderer` -- prefab 通常常驻,不建议频繁 unload - -### 9.2 特效 / 粒子 - -建议: - -- 区分关键特效与普通特效 -- 普通特效允许 `DropNewestRequest` -- 回收时必须清理所有粒子系统、Trail、音效播放状态 -- 支持“播完自动回池” -- 预热由场景和技能装配共同驱动 - -### 9.3 怪物 / NPC - -建议: - -- 不建议只依赖通用 `SetActive` -- 必须实现 `IGameObjectPoolable` -- 推荐支持 `SleepWake` -- 必须有 `minRetained` -- 池满时不建议直接 `null` -- 场景切换 / 波次结束后再做结构性收缩 - -### 9.4 掉落物 / 临时交互物 - -建议: - -- 适合通用池 -- 支持超时自动回收 -- 支持来源信息重置 - -### 9.5 飘字 / World UI - -建议: - -- 高度适合池化 -- 必须自动回收 -- 必须重置 tween / alpha / scale / text / follow target - ---- - -## 10. 预热策略设计 - -### 10.1 预热阶段 - -预热必须是分阶段的,而不是只靠初始化时一次性完成。 - -建议阶段: - -- `AppInitialize` -- `SceneLoad` -- `BattlePrepare` -- `WavePrepare` -- `OnDemand` - -### 10.2 预热预算 - -预热不允许无限制同步创建。 - -建议加入: - -- 每帧最大创建数 `warmupBatchPerFrame` -- 每帧时间预算 `warmupFrameBudgetMs` -- 大对象延迟到非关键帧创建 - -### 10.3 自适应预热 - -建议收集以下统计并用于反哺配置: - -- `peakActive` -- `peakTotal` -- `missCount` -- `expandCount` -- `poolExhaustedCount` - -由此生成: - -- 推荐 `softCapacity` -- 推荐 `prewarmCount` -- 推荐 `minRetained` - ---- - -## 11. 淘汰策略设计 - -### 11.1 默认原则 - -淘汰不能只看时间,还应结合: - -- 空闲时间 -- 对象优先级 -- 当前是否战斗中 -- 当前内存压力 -- 当前池容量是否超过软上限 - -### 11.2 推荐容量模型 - -- `minRetained` - 最低保有量,正常回收不低于该值 -- `softCapacity` - 常态推荐容量 -- `hardCapacity` - 绝对上限 - -### 11.3 销毁预算 - -回收策略必须预算化: - -- 每 tick 最多回收 `trimBatchPerTick` -- 必要时可以带时间预算,例如每帧不超过 `X ms` - -这样可避免同一帧大量 `Destroy` - -### 11.4 低内存策略 - -当收到 `Application.lowMemory` 时: - -- 忽略部分 `minRetained` -- 优先回收低优先级池 -- 优先卸载不常用 prefab -- 进入短时激进回收模式 - ---- - -## 12. 调度策略设计 - -当前全量扫描策略不适合作为最终版。 - -推荐: - -- 用最小堆维护池的下次清理时间 -- 池状态变化时只更新自己的 `nextDueTime` -- 调度器只处理到期池 -- 清理和预热都按 budget 驱动 - -这样可以避免: - -- 每次回收都扫描所有池 -- 大量池同时存在时的调度浪费 - ---- - -## 13. 自动回收设计 - -推荐提供一组通用 helper / component: - -- `ReturnToPoolAfterSeconds` -- `ReturnToPoolOnParticleStopped` -- `ReturnToPoolOnAnimatorStateExit` -- `ReturnToPoolOnAudioFinished` -- `ReturnToPoolOnDistanceExceeded` -- `ReturnToPoolOnCollision` - -目标: - -- 业务不重复造轮子 -- 自动回收行为可视化配置 -- 减少“忘记 Release”导致的泄漏 - ---- - -## 14. 运行时统计设计 - -最优方案必须带统计闭环。 - -每个池建议统计: - -- `acquireCount` -- `releaseCount` -- `hitCount` -- `missCount` -- `peakActive` -- `peakTotal` -- `expandCount` -- `exhaustedCount` -- `autoRecycleCount` -- `destroyCount` -- `avgLifetime` -- `avgIdleTime` -- `avgAcquireCostMs` -- `avgReleaseCostMs` - -调试用途: - -- Inspector 面板 -- 运行时快照 -- CSV / JSON 导出 -- 自动生成调优建议 - ---- - -## 15. 推荐默认配置区间 - -以下是默认建议值,不是硬编码结论,应由运行时统计修正。 - -### 15.1 通用默认 - -- `minRetained = 2 ~ 8` -- `softCapacity = 8 ~ 32` -- `hardCapacity = softCapacity * 1.5 ~ 2` -- `idleTrimDelay = 15s ~ 60s` -- `prefabUnloadDelay = 60s ~ 300s` -- `trimBatchPerTick = 1 ~ 4` - -### 15.2 子弹默认 - -- `minRetained = 16` -- `softCapacity = 64` -- `hardCapacity = 128` -- `overflowPolicy = AutoExpand` -- `prefabUnloadDelay = 300s` - -### 15.3 普通特效默认 - -- `minRetained = 4` -- `softCapacity = 16` -- `hardCapacity = 32` -- `overflowPolicy = DropNewestRequest` -- `idleTrimDelay = 20s` - -### 15.4 怪物默认 - -- `minRetained = 2` -- `softCapacity = 8` -- `hardCapacity = 16` -- `overflowPolicy = AutoExpand` -- `activationMode = SleepWake` - ---- - -## 16. 与当前实现的映射关系 - -当前模块中可保留的部分: - -- `GameObjectPoolManager` - 继续作为总入口和调度器雏形 -- `RuntimePrefabPool` - 继续作为单 prefab 池雏形 -- `PoolConfig` - 升级为新配置模型的一部分 -- `IResourceLoader` - 可继续作为资源加载抽象 - -需要重点重构的部分: - -- 实例生命周期协议 -- 池满策略 -- 预热与清理预算调度 -- 统计系统 -- 自动回收组件 -- 怪物/特效/子弹的分类默认策略 - ---- - -## 17. 迁移路线 - -建议分四个阶段落地。 - -### 阶段 1:补生命周期协议 - -目标: - -- 引入 `IGameObjectPoolable` -- Acquire / Release 时统一回调 -- 允许对象自定义重置 - -### 阶段 2:补配置模型 - -目标: - -- 引入 `PoolProfile + PoolRule` -- 加入 `minRetained / softCapacity / hardCapacity / overflowPolicy` -- 兼容旧 `PoolConfig` - -### 阶段 3:补自动回收与预算调度 - -目标: - -- 自动回收 helper -- 分帧 warmup -- 预算式 trim -- 低内存模式 - -### 阶段 4:补统计与业务门面 - -目标: - -- 运行时统计面板 -- 容量推荐导出 -- `EnemyPool / BulletPool / FxPool` 业务门面 - ---- - -## 18. 最终结论 - -最优对象池方案不是单一 `GameObject` 缓存容器,而是: - -- 以 prefab 池为底层 -- 以生命周期协议为核心 -- 以分类策略为手段 -- 以预算调度为性能保障 -- 以统计闭环为调优依据 - -如果后续按本文档实施,建议优先级如下: - -1. `IGameObjectPoolable` 与 `PoolSpawnContext` -2. `PoolProfile + PoolRule` -3. `PoolOverflowPolicy` -4. 自动回收 helper -5. 分帧预热与预算清理 -6. 运行时统计与调优导出 - diff --git a/Runtime/ABase/GameObjectPool/fe.md.meta b/Runtime/ABase/GameObjectPool/fe.md.meta deleted file mode 100644 index 0cd47ba..0000000 --- a/Runtime/ABase/GameObjectPool/fe.md.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: c1c2737cf20d46c7814c0552b7f0720d -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: