From 584a4b1b91b732e0c44e7ea3d3061badfc2ff43a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E6=80=9D=E6=B5=B7?= <1464576565@qq.com> Date: Wed, 25 Mar 2026 11:18:17 +0800 Subject: [PATCH] 11 --- Client/Assets/ObjectPoolSystemDesign.md | 923 ------------------ .../Simulate/DefaultPackage_Simulate.bytes | Bin 1507 -> 1507 bytes .../Simulate/DefaultPackage_Simulate.hash | 2 +- .../Simulate/DefaultPackage_Simulate.json | 2 +- Client/Packages/com.alicizax.unity.framework | 2 +- Client/UserSettings/EditorUserSettings.asset | 4 +- Client/UserSettings/Layouts/default-2022.dwlt | 138 +-- 7 files changed, 74 insertions(+), 997 deletions(-) delete mode 100644 Client/Assets/ObjectPoolSystemDesign.md diff --git a/Client/Assets/ObjectPoolSystemDesign.md b/Client/Assets/ObjectPoolSystemDesign.md deleted file mode 100644 index d2848e4..0000000 --- a/Client/Assets/ObjectPoolSystemDesign.md +++ /dev/null @@ -1,923 +0,0 @@ -# 高性能对象池系统设计文档 - -## 1. 设计目标 - -本文设计一个面向 Unity 大型项目的对象池系统,目标不是“能用”,而是同时满足以下要求: - -- 高性能:热点路径稳定 O(1) 或近似 O(1),避免全表扫描进入业务帧。 -- 低内存:控制元数据膨胀,支持容量上限、分层配额、预热与回收策略。 -- 0GC:运行时热点路径不产生托管垃圾,调试和统计默认不侵入业务路径。 -- 高扩展:支持 GameObject、纯 C# 对象、句柄对象、资源实例、复合对象、分片对象。 -- 易调试:运行时诊断与编辑器面板分离,支持快照、采样、事件流和错误定位。 -- 适合大型项目:支持多域、多场景、多模块、多团队协作,不依赖单一对象模型。 -- 支持复杂池子:支持多 Key、多状态、多生命周期、多租户、异步预热、延迟销毁。 - -这套系统默认服务“小众但大型”的 Unity 项目,即: - -- 代码量大,模块边界复杂。 -- 有长期演进需求,不能接受一次性写死。 -- 对线上性能和可观测性要求高。 -- 池子类型多,不只是子弹和特效。 - -## 2. 非目标 - -以下能力不作为第一阶段核心目标: - -- 透明跨线程直接复用 UnityEngine.Object。 -- 自动把任意未池化代码转换成池化逻辑。 -- 用一套 API 完全覆盖所有业务差异。 -- 在所有对象类型上强行追求完全一致的内部实现。 - -原因很简单:对象池的统一接口可以统一,但底层策略不能假装一样。GameObject、原生资源句柄、纯托管对象、本地缓存块,本质差异很大,强行统一通常会换来性能和可维护性同时变差。 - -## 3. 总体架构 - -系统分为 6 层: - -1. `PoolService` -2. `PoolDomain` -3. `PoolRegistry` -4. `PoolCore` -5. `PoolPolicy` -6. `PoolDiagnostics` - -职责如下: - -- `PoolService`:全局入口,负责生命周期、配置装载、域管理、更新调度。 -- `PoolDomain`:逻辑域隔离。比如 `UI`、`FX`、`Gameplay`、`Net`、`Addressable` 各自独立。 -- `PoolRegistry`:注册池定义、类型工厂、键类型、扩展策略。 -- `PoolCore`:真正的池实现,处理获取、归还、预热、扩容、淘汰。 -- `PoolPolicy`:定义创建、重置、校验、回收、容量、淘汰和调试采样策略。 -- `PoolDiagnostics`:只读观测层,负责统计快照、事件记录、调试视图和导出。 - -核心原则: - -- 业务代码不直接碰底层容器。 -- 池核心不直接依赖编辑器。 -- 统计系统不阻塞业务路径。 -- 高级功能通过策略和扩展挂上去,而不是污染主流程。 - -## 4. 模块拆分 - -建议目录: - -```text -Runtime/ - Pool/ - Core/ - Handle/ - Policy/ - Registry/ - Domain/ - Diagnostics/ - Adapters/ - Unsafe/ -Editor/ - Pool/ - Window/ - Inspector/ - Profiler/ -Tests/ - Runtime/ - Editor/ -``` - -### 4.1 Core - -核心只保留高频逻辑: - -- `Rent` -- `Return` -- `TryRent` -- `Prewarm` -- `Trim` -- `Shutdown` - -### 4.2 Policy - -策略层负责差异化: - -- 创建策略 -- 重置策略 -- 释放策略 -- 容量策略 -- 淘汰策略 -- 健康检查策略 -- 调试命名策略 - -### 4.3 Diagnostics - -诊断层只订阅事件,不进入关键路径的复杂计算。 - -### 4.4 Adapters - -适配层处理: - -- `GameObject` -- `Component` -- `ScriptableObject` -- `NativeArray` 包装 -- `Addressables` 实例 -- 自定义资源句柄 - -## 5. 核心对象模型 - -我不会让业务对象强制继承一个 `ObjectBase`。继承式对象池扩展性很差,会把“池系统”反向侵入所有业务对象。 - -我会采用“组合 + 句柄”模型。 - -### 5.1 核心接口 - -```csharp -public interface IPool -{ - PoolId Id { get; } - PoolRuntimeInfo RuntimeInfo { get; } -} - -public interface IPool : IPool -{ - PoolHandle Rent(); - bool TryRent(out PoolHandle handle); - void Return(in PoolHandle handle); - void Prewarm(int count); - void Trim(int count); -} - -public interface IPoolFactory -{ - T Create(); - void Destroy(T item); -} - -public interface IPoolLifecycle -{ - void OnCreate(T item); - void OnRent(T item); - void OnReturn(T item); - void OnReset(T item); - bool CanRecycle(T item); -} -``` - -### 5.2 句柄设计 - -`PoolHandle` 是值类型句柄,不直接暴露池内部节点引用: - -```csharp -public readonly struct PoolHandle -{ - public readonly T Value; - internal readonly int SlotIndex; - internal readonly ushort Version; - internal readonly PoolId PoolId; -} -``` - -作用: - -- 防止重复归还。 -- 防止把 A 池的对象还到 B 池。 -- 支持失效检测。 -- 允许调试系统用句柄定位历史事件。 - -这个设计比“直接传对象归还”更适合大型项目,因为大型项目里误还、重还、跨池还、跨域还都很常见。 - -## 6. 数据结构设计 - -### 6.1 主存储结构 - -每个池维护以下固定结构: - -- `Slot[] _slots` -- `int _freeHead` -- `int _activeCount` -- `int _inactiveCount` -- `FastQueue _inactiveQueue` -- `FastMap` 或 `Dictionary` -- `BitSet _inUseBits` -- `BitSet _dirtyBits` - -其中 `Slot` 包含: - -```csharp -internal struct Slot -{ - public T Item; - public int NextFree; - public int NextInBucket; - public int PrevInBucket; - public int StateFlags; - public int LastRentTick; - public int LastReturnTick; - public ushort Version; - public int RentCount; - public int OwnerThreadId; -} -``` - -设计意图: - -- 不用链表节点对象,避免额外分配和引用跳转。 -- 尽量数组化,提升缓存命中率。 -- 用索引串联空闲链和桶链,避免托管容器层层嵌套。 - -### 6.2 Why not LinkedList / MultiDictionary - -我不会把“按名字多值管理”建立在 `LinkedListNode` 和泛型多值字典上,原因是: - -- 节点对象本身有额外内存占用。 -- 指针跳转多,缓存局部性差。 -- 按名字查桶后仍可能线性扫完整桶。 -- 热点路径结构太泛化,不够专门化。 - -更好的做法是: - -- 预先把每个对象映射到 `slotIndex`。 -- 每个 Key 有自己的空闲链和活跃链。 -- 对“可租用集合”和“所有对象集合”分开维护。 - -### 6.3 双索引模型 - -对于复杂项目,我会同时维护两种索引: - -- `Item -> SlotIndex`:归还、校验、调试定位。 -- `Key -> AvailableHead`:按键快速获取可用对象。 - -这样 `Rent(key)` 不需要扫描整个桶,只需要从该 Key 的可用链表头部直接拿一个元素。 - -这比“遍历名字桶,找到第一个没在用的对象”要稳定得多。 - -## 7. 核心状态机 - -单个池内对象状态定义: - -- `Uninitialized` -- `Available` -- `Reserved` -- `InUse` -- `Returning` -- `Disposed` - -### 7.1 状态迁移 - -正常路径: - -- Create -> Available -- Available -> Reserved -- Reserved -> InUse -- InUse -> Returning -- Returning -> Available -- Available -> Disposed - -异常保护: - -- 已归还句柄再次归还,直接拒绝。 -- 版本不匹配,直接判定句柄失效。 -- 正在释放或已销毁对象,拒绝租用。 - -`Reserved` 这个状态不是多余的,它是给以下场景准备的: - -- 异步加载后的延迟激活 -- 跨系统交接 -- 带初始化流水线的对象 -- 需要分两阶段构建的复杂实例 - -## 8. 0GC 设计原则 - -0GC 不是口号,必须明确哪些路径严格零分配。 - -### 8.1 严格 0GC 的路径 - -- `Rent` -- `TryRent` -- `Return` -- `Fast Validate` -- `按 Key 查询可用数量` -- `池内状态位更新` - -### 8.2 允许分配的路径 - -- 首次创建池 -- 扩容 -- 预热 -- 编辑器快照 -- 导出 CSV / JSON -- 显式调试采样 - -### 8.3 实现要求 - -- 不在热点路径创建委托、闭包、枚举器类。 -- 不返回 `IEnumerable` 给业务热路径。 -- 不在热点路径 new `List<>`。 -- 不依赖反射创建对象。 -- 不在热点路径拼接字符串。 -- 不在运行时默认收集完整调用栈。 - -### 8.4 时间戳设计 - -我不会用 `DateTime.UtcNow` 记录热点使用时间。 - -我会统一使用: - -- `int tick` -- `uint frameIndex` -- `double realtimeSinceStartup` - -其中热路径记录 `frameIndex` 或逻辑 `tick`,只有调试导出时再转换成人类可读时间。 - -原因: - -- 更轻 -- 更稳定 -- 更容易做排序和过期比较 -- 更适合回放与录制 - -## 9. 获取与归还算法 - -### 9.1 Rent - -目标复杂度: - -- `Rent()`:O(1) -- `Rent(key)`:O(1) - -基本步骤: - -1. 从 `key available head` 拿 `slotIndex` -2. 校验 `slot` 状态和版本 -3. 从可用链移除 -4. 标记 `InUse` -5. 更新计数、tick、统计 -6. 调用 `OnRent` -7. 返回值类型句柄 - -### 9.2 Return - -目标复杂度: - -- `Return(handle)`:O(1) - -基本步骤: - -1. 校验池 ID -2. 校验版本号 -3. 校验状态必须为 `InUse` -4. 调用 `CanRecycle` -5. 调用 `OnReturn` -6. 调用 `OnReset` -7. 放回 `key available chain` -8. 更新统计 - -### 9.3 扩容 - -扩容不是每次 `+1`,而是分级策略: - -- 小池:2 倍扩容 -- 中池:1.5 倍扩容 -- 大池:固定块增长 - -原因: - -- 小池要减少扩容次数 -- 大池要控制峰值浪费 - -## 10. 容量与回收策略 - -大型项目不能只有一个 `Capacity`。 - -我会支持以下层级: - -- `MinCapacity` -- `SoftCapacity` -- `HardCapacity` -- `PrewarmCapacity` -- `PerKeySoftCapacity` -- `PerDomainBudget` - -### 10.1 容量语义 - -- `MinCapacity`:至少保留,不主动裁剪。 -- `SoftCapacity`:超过后进入延迟裁剪候选。 -- `HardCapacity`:超过后禁止继续扩容,走降级策略。 -- `PerDomainBudget`:整个域共享内存预算,防止单池失控。 - -### 10.2 回收策略 - -不做“每次超容立刻全量扫描”,而是做三段式: - -1. 标记超容 -2. 放入裁剪队列 -3. 在预算帧内分批处理 - -这很关键。大型项目最怕把维护性工作同步砸进战斗帧。 - -### 10.3 裁剪候选组织 - -每个池维护一个“可裁剪最小堆”或分层队列,排序因子可配置: - -- 最久未使用 -- 最低优先级 -- 冷热分层 -- Key 局部配额 -- 是否锁定 - -这样 `Trim` 可以渐进式处理,而不是每次遍历全池。 - -## 11. 多 Key / 复杂池支持 - -一个现代对象池不能只支持“按 name 拿对象”。 - -我会支持以下 Key 模型: - -- `PoolKey.None` -- `int` -- `FixedString64` -- 复合 Key -- 结构化 Key - -例如: - -```csharp -public struct FxPoolKey -{ - public int FxId; - public byte QualityLevel; - public byte Theme; -} -``` - -应用场景: - -- 同一特效不同质量等级 -- 同一 UI Cell 不同模板 -- 同一角色不同皮肤部件 -- 同一网络包对象不同协议版本 - -### 11.1 多态池 - -支持一个池管理多个派生类型,但不是默认开启。 - -理由: - -- 多态池灵活,但查找和重置逻辑更复杂。 -- 默认建议一池一类型,特殊场景再用联合池。 - -联合池通过注册表完成: - -- `BaseTypePool` -- 子类型工厂映射 -- 子类型生命周期映射 - -## 12. 特殊类型池设计 - -### 12.1 GameObject 池 - -特点: - -- 需要处理激活状态 -- 需要处理父节点 -- 需要处理场景归属 -- 需要处理组件重置成本 - -建议: - -- 池内对象挂 `PooledInstanceTag` -- 禁止业务直接 `Destroy` -- 使用 `PoolHandle` -- `OnReset` 里只做必要重置,不做全组件反射扫描 - -### 12.2 Component 池 - -对外返回 `TComponent`,内部仍以宿主实例为核心管理,避免组件和对象分离失控。 - -### 12.3 纯托管对象池 - -适合: - -- 临时上下文 -- 行为树节点运行数据 -- 网络解析缓存对象 -- UI 虚拟列表单元数据容器 - -优先使用泛型池,不依赖 Unity 生命周期。 - -### 12.4 集合池 - -单独提供高频集合池: - -- `ListPool` -- `DictionaryPool` -- `HashSetPool` -- `StringBuilderPool` - -但集合池必须分离于主对象池系统,不要共用复杂的池元数据。 - -原因: - -- 集合池需求简单 -- 热点极多 -- 追求极低开销 - -### 12.5 原生内存包装池 - -支持包装: - -- `NativeArray` -- `NativeList` -- `UnsafeList` - -但要求: - -- 主线程与 Job 边界清晰 -- 回收前必须完成 Job 依赖 -- 诊断系统记录 owner 和 frame fence - -### 12.6 异步资源实例池 - -例如 Addressables: - -- `Create` 可能异步 -- `Return` 后不能立刻销毁 -- 实例可能依赖引用计数 - -对此引入 `AsyncPoolAdapter`: - -- 支持 `ReserveAsync` -- 支持加载中状态 -- 支持失败回滚 -- 支持 warmup pipeline - -## 13. 扩展点设计 - -### 13.1 Policy 驱动 - -每个池通过配置组合: - -- `Factory` -- `Lifecycle` -- `CapacityPolicy` -- `TrimPolicy` -- `ValidationPolicy` -- `DebugNameProvider` - -### 13.2 Feature Flag - -不是所有池都启用所有能力。 - -例如按位配置: - -- `TrackStackTrace` -- `TrackOwner` -- `EnableDoubleReturnCheck` -- `EnableLeakDetection` -- `EnablePerItemMetrics` -- `EnableAsyncReserve` - -低端池只开基础能力,高风险池再开强诊断。 - -### 13.3 自定义验证器 - -```csharp -public interface IPoolValidator -{ - PoolValidationResult ValidateOnRent(T item); - PoolValidationResult ValidateOnReturn(T item); -} -``` - -用来做: - -- GameObject 是否被外部销毁 -- 资源引用是否断裂 -- Component 缓存是否失效 -- Native 容器是否已释放 - -## 14. 调试与观测设计 - -调试要“非常轻松方便”,但不能靠在 Inspector 每帧遍历整个池。 - -我的做法是“事件流 + 快照缓存 + 编辑器订阅”。 - -### 14.1 运行时观测层 - -运行时只维护固定大小统计: - -- 总租用次数 -- 总归还次数 -- 当前活跃数 -- 当前空闲数 -- 峰值活跃数 -- 创建次数 -- 销毁次数 -- 扩容次数 -- 裁剪次数 -- 失败租用次数 - -这些都存在 struct 里,常量开销更新。 - -### 14.2 环形事件缓冲 - -仅在开启诊断时记录事件到无锁环形缓冲: - -- Rent -- Return -- Grow -- Trim -- LeakWarning -- InvalidReturn -- DestroyOutsidePool - -每条事件固定大小,不分配字符串正文,只记录: - -- `PoolId` -- `SlotIndex` -- `Frame` -- `EventType` -- `Arg0` -- `Arg1` - -UI 读取时再解码。 - -### 14.3 快照机制 - -编辑器面板不直接扫运行时容器,而是请求一个“快照构建器”: - -- 默认每 500ms 构建一次 -- 只在窗口可见时工作 -- 可按域、池名、类型过滤 -- 可显示 Top N 热池 - -快照属于调试层分配,不污染业务路径。 - -### 14.4 泄漏检测 - -泄漏检测分等级: - -- Level 0:只统计未归还数量 -- Level 1:记录最近 owner id -- Level 2:记录采样调用栈 - -调用栈采样不能默认全开,只能: - -- 仅编辑器 -- 仅开发构建 -- 仅采样部分对象 -- 仅指定池启用 - -### 14.5 Debug 面板能力 - -我会做以下视图: - -- 域总览 -- 池列表 -- 单池详情 -- Key 分布 -- 活跃对象列表 -- 最近错误事件 -- 租用热点排行 -- 裁剪压力排行 -- 扩容时间线 -- 泄漏嫌疑列表 - -并支持: - -- 搜索 -- 排序 -- 冻结快照 -- 导出报告 -- 点击对象定位场景实例 - -## 15. 线程模型 - -Unity 项目里线程问题不能模糊。 - -### 15.1 主线程池 - -默认所有 Unity 对象池都归主线程管理。 - -### 15.2 Worker 池 - -纯托管对象池可选线程安全版本。 - -线程安全不是给所有池统一加锁,而是分实现: - -- `MainThreadPool` -- `ConcurrentPool` - -原因: - -- 主线程池要极致轻量 -- 并发池要接受额外同步成本 - -### 15.3 Job 边界 - -如果池对象会跨 Job 使用,必须通过显式借用协议: - -- 主线程 `Rent` -- 写入 job token -- job 完成后 `Return` - -不允许在 Job 内直接操作托管池。 - -## 16. 错误防护 - -大型项目里最值钱的是“错误早点炸,而且能查到是谁干的”。 - -系统必须捕获: - -- 双重归还 -- 跨池归还 -- 归还已失效句柄 -- 外部销毁池对象 -- 未初始化对象进入可用链 -- 锁定对象被裁剪 -- 异步加载失败后错误入池 - -### 16.1 处理策略 - -不同构建等级不同处理: - -- `Editor/Dev`:强校验 + 报错 + 事件记录 -- `Release`:快速失败 + 计数器上报 + 可选降级 - -### 16.2 降级策略 - -当池进入异常状态,可选: - -- 拒绝继续租用 -- 回退到直创建直销毁 -- 标记池熔断 -- 上报监控并隔离该域 - -## 17. 配置系统 - -大型项目不能全靠代码硬编码。 - -建议配置对象: - -- `PoolDomainConfig` -- `PoolDefinitionAsset` -- `PoolRuntimeOverride` - -配置字段包括: - -- PoolId -- 类型 -- Key 类型 -- 预热数量 -- 容量阈值 -- 扩容策略 -- 裁剪策略 -- 调试等级 -- 泄漏检测等级 -- 场景切换策略 -- 低内存回调策略 - -### 17.1 配置分层 - -- 默认配置 -- 平台配置 -- 场景配置 -- 运行时覆盖 - -例如移动端和 PC 不应该共享完全相同的池容量。 - -## 18. 生命周期与场景切换 - -对象池需要明确域生命周期: - -- `Global` -- `Scene` -- `Match` -- `Feature` -- `Temporary` - -### 18.1 场景池 - -进入场景时预热,退出场景时可批量回收或转移。 - -### 18.2 Global 池 - -如 UI 和通用 FX,不随场景直接销毁,但需要做场景引用清洗。 - -### 18.3 Temporary 池 - -例如一次性事件活动模块,生命周期结束直接销毁整个域。 - -## 19. 性能预算建议 - -建议在设计时就定义预算: - -- `Rent/Return` 平均 < 0.5us -- `Trim` 支持分帧预算,如每帧最多处理 16 或 32 个候选 -- Debug 关闭时每池统计更新为常量成本 -- 快照构建不进入游戏主热帧 - -### 19.1 大池优化建议 - -当池数量 > 100 或对象总量 > 100000 时: - -- 禁止全池排序式裁剪 -- 禁止调试全量对象枚举默认开启 -- 使用域级调度队列 -- 使用 Top-K 热点缓存代替实时全排序 - -## 20. 测试策略 - -必须覆盖: - -- 单线程正确性 -- 高频 Rent/Return 压测 -- 大容量扩缩容 -- Key 分桶正确性 -- 双重归还检测 -- 无效句柄检测 -- 异步加载失败回滚 -- 场景切换清理 -- 泄漏检测 -- 调试快照一致性 - -### 20.1 Benchmark - -基准要对比: - -- 当前实现 -- 新实现 -- Unity 内置 `ObjectPool` -- 直创建直销毁 - -指标: - -- CPU -- GC Alloc -- Peak Memory -- P99 延迟 -- Trim 尖峰 - -## 21. 推荐的最小落地版本 - -如果让我先做第一版,不会一次塞满所有高级功能,而是按下面顺序: - -### Phase 1 - -- `MainThreadPool` -- 值类型句柄 -- 固定数组槽位 -- O(1) Rent/Return -- 基础预热和扩容 -- 基础统计 -- Dev 下双重归还检测 - -### Phase 2 - -- 多 Key 支持 -- 分帧 Trim -- 域与预算 -- GameObject / Component 适配器 -- 编辑器快照面板 - -### Phase 3 - -- 异步资源实例池 -- 泄漏采样 -- Native 包装池 -- 并发池 -- 报表导出和线上遥测 - -## 22. 我会避免的设计 - -以下方案我不会采用: - -- 强制所有池对象继承统一基类 -- 用字符串当唯一主 Key 贯穿所有热路径 -- 超容后立刻全表扫描清理 -- 每帧在 Inspector 里直接遍历完整池状态 -- 在热路径用 `DateTime.UtcNow` -- 在热路径构造 `List<>`、`ToArray()`、LINQ -- 为了“统一”而让所有池都加线程锁 -- 调试信息和业务数据共用同一套重型结构 - -## 23. 总结 - -如果要同时做到高性能、低内存、0GC、高扩展、易调试,我的核心思路是: - -- 用数组槽位和索引链代替托管链表对象。 -- 用句柄和版本号解决大型项目里的误用问题。 -- 用多索引结构保证 `Rent/Return` 真正稳定。 -- 用分帧预算和候选队列替代同步全表释放。 -- 让调试成为旁路系统,而不是主路径负担。 -- 不强迫所有类型共用一种对象模型,而是统一接口、分离适配器。 - -这套设计的关键不是“对象池”,而是“把对象池当成一套运行时基础设施”来做。只有这样,它才扛得住大型项目、复杂类型、长期演进和多人协作。 - -## 24. 后续实现建议 - -如果继续往下落地,我建议按这个顺序开发: - -1. 先实现纯 C# 泛型池核心,完成句柄、槽位、版本、O(1) 可用链。 -2. 再实现 GameObject 适配器,不要一开始就把 Unity 特性揉进核心。 -3. 接着做域、预算和分帧裁剪,否则大项目上线后一定出现维护尖峰。 -4. 最后做调试窗口和快照系统,确保调试能力强但不反噬运行时。 - -如果你愿意,我下一步可以直接基于这份文档,在 `Packages/com.alicizax.unity.framework/Runtime/ABase/ObjectPool` 旁边给你起一版可落地的代码骨架。 diff --git a/Client/Bundles/StandaloneWindows64/DefaultPackage/Simulate/DefaultPackage_Simulate.bytes b/Client/Bundles/StandaloneWindows64/DefaultPackage/Simulate/DefaultPackage_Simulate.bytes index b6d7f38280194e4c3cd8a1c3b2bce3de9219194a..e9127c9bb2b53150bd83c07a21c70ad1791bbda7 100644 GIT binary patch delta 18 ZcmaFN{g`_~0=t=&iGh`g`Ns4bRscP11?B(% delta 18 ZcmaFN{g`_~0=uD=v89!v#m4j+RscO{1?K<& diff --git a/Client/Bundles/StandaloneWindows64/DefaultPackage/Simulate/DefaultPackage_Simulate.hash b/Client/Bundles/StandaloneWindows64/DefaultPackage/Simulate/DefaultPackage_Simulate.hash index e1abd8c..9228fd0 100644 --- a/Client/Bundles/StandaloneWindows64/DefaultPackage/Simulate/DefaultPackage_Simulate.hash +++ b/Client/Bundles/StandaloneWindows64/DefaultPackage/Simulate/DefaultPackage_Simulate.hash @@ -1 +1 @@ -3c0a1701 \ No newline at end of file +d4b50d90 \ No newline at end of file diff --git a/Client/Bundles/StandaloneWindows64/DefaultPackage/Simulate/DefaultPackage_Simulate.json b/Client/Bundles/StandaloneWindows64/DefaultPackage/Simulate/DefaultPackage_Simulate.json index 2a24863..3066a95 100644 --- a/Client/Bundles/StandaloneWindows64/DefaultPackage/Simulate/DefaultPackage_Simulate.json +++ b/Client/Bundles/StandaloneWindows64/DefaultPackage/Simulate/DefaultPackage_Simulate.json @@ -10,7 +10,7 @@ "BuildPipeline": "EditorSimulateBuildPipeline", "PackageName": "DefaultPackage", "PackageVersion": "Simulate", - "PackageNote": "2026/3/24 11:39:18", + "PackageNote": "2026/3/24 16:40:47", "AssetList": [ { "Address": "Click", diff --git a/Client/Packages/com.alicizax.unity.framework b/Client/Packages/com.alicizax.unity.framework index d5518c4..76cc128 160000 --- a/Client/Packages/com.alicizax.unity.framework +++ b/Client/Packages/com.alicizax.unity.framework @@ -1 +1 @@ -Subproject commit d5518c46b1d84f3103ad49d35eff6889e93e5b4a +Subproject commit 76cc128c4f9744150c2af60d5b2b06fc20249059 diff --git a/Client/UserSettings/EditorUserSettings.asset b/Client/UserSettings/EditorUserSettings.asset index d0c7a7a..d7386d6 100644 --- a/Client/UserSettings/EditorUserSettings.asset +++ b/Client/UserSettings/EditorUserSettings.asset @@ -30,10 +30,10 @@ EditorUserSettings: value: 0606045450065e5d55575a241522064444161c797f7b7234757c4f32e1b0353d flags: 0 RecentlyUsedSceneGuid-7: - value: 5a07065703500c59585e0e7748770d44444f4a737d2d7f35787d4f63e0b26668 + value: 5001560504060c590f5b0f7245725a44404f1d7c297e2233787e4a36b5e4666b flags: 0 RecentlyUsedSceneGuid-8: - value: 5001560504060c590f5b0f7245725a44404f1d7c297e2233787e4a36b5e4666b + value: 5a07065703500c59585e0e7748770d44444f4a737d2d7f35787d4f63e0b26668 flags: 0 RecentlyUsedSceneGuid-9: value: 50500404540c580d0f0b5e7543725b44424f4c7a7b7c7734747e4f36e4b1676d diff --git a/Client/UserSettings/Layouts/default-2022.dwlt b/Client/UserSettings/Layouts/default-2022.dwlt index 27183a0..8f0598c 100644 --- a/Client/UserSettings/Layouts/default-2022.dwlt +++ b/Client/UserSettings/Layouts/default-2022.dwlt @@ -40,9 +40,9 @@ MonoBehaviour: m_Position: serializedVersion: 2 x: 0 - y: 426 - width: 629 - height: 521 + y: 665 + width: 485 + height: 282 m_MinSize: {x: 51, y: 71} m_MaxSize: {x: 4001, y: 4021} m_ActualView: {fileID: 14} @@ -70,7 +70,7 @@ MonoBehaviour: serializedVersion: 2 x: 0 y: 0 - width: 629 + width: 485 height: 947 m_MinSize: {x: 100, y: 100} m_MaxSize: {x: 8096, y: 16192} @@ -174,7 +174,7 @@ MonoBehaviour: m_MinSize: {x: 400, y: 100} m_MaxSize: {x: 32384, y: 16192} vertical: 0 - controlID: 152 + controlID: 24 draggingID: 0 --- !u!114 &8 MonoBehaviour: @@ -193,10 +193,10 @@ MonoBehaviour: serializedVersion: 2 x: 0 y: 0 - width: 629 - height: 426 - m_MinSize: {x: 200, y: 200} - m_MaxSize: {x: 4000, y: 4000} + width: 485 + height: 665 + m_MinSize: {x: 201, y: 221} + m_MaxSize: {x: 4001, y: 4021} m_ActualView: {fileID: 16} m_Panes: - {fileID: 16} @@ -219,14 +219,14 @@ MonoBehaviour: - {fileID: 11} m_Position: serializedVersion: 2 - x: 629 + x: 485 y: 0 - width: 257 + width: 396 height: 947 m_MinSize: {x: 100, y: 100} m_MaxSize: {x: 8096, y: 16192} vertical: 1 - controlID: 49 + controlID: 70 draggingID: 0 --- !u!114 &10 MonoBehaviour: @@ -245,8 +245,8 @@ MonoBehaviour: serializedVersion: 2 x: 0 y: 0 - width: 257 - height: 497 + width: 396 + height: 595 m_MinSize: {x: 200, y: 200} m_MaxSize: {x: 4000, y: 4000} m_ActualView: {fileID: 17} @@ -270,9 +270,9 @@ MonoBehaviour: m_Position: serializedVersion: 2 x: 0 - y: 497 - width: 257 - height: 450 + y: 595 + width: 396 + height: 352 m_MinSize: {x: 102, y: 121} m_MaxSize: {x: 4002, y: 4021} m_ActualView: {fileID: 18} @@ -295,9 +295,9 @@ MonoBehaviour: m_Children: [] m_Position: serializedVersion: 2 - x: 886 + x: 881 y: 0 - width: 414 + width: 455 height: 947 m_MinSize: {x: 232, y: 271} m_MaxSize: {x: 10002, y: 10021} @@ -321,9 +321,9 @@ MonoBehaviour: m_Children: [] m_Position: serializedVersion: 2 - x: 1300 + x: 1336 y: 0 - width: 620 + width: 584 height: 947 m_MinSize: {x: 275, y: 50} m_MaxSize: {x: 4000, y: 4000} @@ -353,9 +353,9 @@ MonoBehaviour: m_Pos: serializedVersion: 2 x: 0 - y: 499 - width: 628 - height: 500 + y: 738 + width: 484 + height: 261 m_SerializedDataModeController: m_DataMode: 0 m_PreferredDataMode: 0 @@ -408,23 +408,23 @@ MonoBehaviour: serializedVersion: 2 x: 0 y: 21 - width: 628 - height: 479 - m_Scale: {x: 0.32708332, y: 0.32708332} - m_Translation: {x: 314, y: 239.5} + width: 484 + height: 240 + m_Scale: {x: 0.22222222, y: 0.22222222} + m_Translation: {x: 242, y: 120} m_MarginLeft: 0 m_MarginRight: 0 m_MarginTop: 0 m_MarginBottom: 0 m_LastShownAreaInsideMargins: serializedVersion: 2 - x: -960.00006 - y: -732.2293 - width: 1920.0001 - height: 1464.4586 + x: -1089 + y: -540 + width: 2178 + height: 1080 m_MinimalGUI: 1 - m_defaultScale: 0.32708332 - m_LastWindowPixelSize: {x: 628, y: 500} + m_defaultScale: 0.22222222 + m_LastWindowPixelSize: {x: 484, y: 261} m_ClearInEditMode: 1 m_NoCameraWarning: 1 m_LowResolutionForAspectRatios: 01000000000000000000 @@ -522,8 +522,8 @@ MonoBehaviour: serializedVersion: 2 x: 0 y: 73 - width: 628 - height: 405 + width: 484 + height: 644 m_SerializedDataModeController: m_DataMode: 0 m_PreferredDataMode: 0 @@ -1059,7 +1059,7 @@ MonoBehaviour: m_OverrideSceneCullingMask: 6917529027641081856 m_SceneIsLit: 0 m_SceneLighting: 1 - m_2DMode: 1 + m_2DMode: 0 m_isRotationLocked: 0 m_PlayAudio: 0 m_AudioPlay: 0 @@ -1094,17 +1094,17 @@ MonoBehaviour: m_Size: {x: 0, y: 0} yGrid: m_Fade: - m_Target: 0 + m_Target: 1 speed: 2 - m_Value: 0 + m_Value: 1 m_Color: {r: 0.5, g: 0.5, b: 0.5, a: 0.4} m_Pivot: {x: 0, y: 0, z: 0} m_Size: {x: 1, y: 1} zGrid: m_Fade: - m_Target: 1 + m_Target: 0 speed: 2 - m_Value: 1 + m_Value: 0 m_Color: {r: 0.5, g: 0.5, b: 0.5, a: 0.4} m_Pivot: {x: 0, y: 0, z: 0} m_Size: {x: 1, y: 1} @@ -1112,17 +1112,17 @@ MonoBehaviour: m_GridAxis: 1 m_gridOpacity: 0.5 m_Rotation: - m_Target: {x: 0, y: 0, z: 0, w: 1} + m_Target: {x: -0.08717229, y: 0.89959055, z: -0.21045254, w: -0.3726226} speed: 2 - m_Value: {x: 0, y: 0, z: 0, w: 1} + m_Value: {x: -0.08717229, y: 0.89959055, z: -0.21045254, w: -0.3726226} m_Size: m_Target: 10 speed: 2 m_Value: 10 m_Ortho: - m_Target: 1 + m_Target: 0 speed: 2 - m_Value: 1 + m_Value: 0 m_CameraSettings: m_Speed: 2 m_SpeedNormalized: 1 @@ -1163,10 +1163,10 @@ MonoBehaviour: m_Tooltip: m_Pos: serializedVersion: 2 - x: 629 + x: 485 y: 73 - width: 255 - height: 476 + width: 394 + height: 574 m_SerializedDataModeController: m_DataMode: 0 m_PreferredDataMode: 0 @@ -1180,23 +1180,23 @@ MonoBehaviour: m_SceneHierarchy: m_TreeViewState: scrollPos: {x: 0, y: 0} - m_SelectedIDs: ea6c0000 + m_SelectedIDs: 3a6d0000 m_LastClickedID: 0 - m_ExpandedIDs: 126cffff1a6cffffbe78ffffe278ffffea78ffffa6c1ffff6ee5ffff7ae5ffff92e5ffff9ae5ffff04fbffff26fbffff28fbfffff4ffffff + m_ExpandedIDs: c6a8ffffc8a8ffffa2aaffff0efbffff10fbfffff4ffffffc8720000 m_RenameOverlay: m_UserAcceptedRename: 0 - m_Name: - m_OriginalName: + m_Name: Cube(Clone) + m_OriginalName: Cube(Clone) m_EditFieldRect: serializedVersion: 2 x: 0 y: 0 width: 0 height: 0 - m_UserData: 0 + m_UserData: -24750 m_IsWaitingForDelay: 0 m_IsRenaming: 0 - m_OriginalEventType: 11 + m_OriginalEventType: 0 m_IsRenamingFilename: 0 m_ClientGUIView: {fileID: 10} m_SearchString: @@ -1226,10 +1226,10 @@ MonoBehaviour: m_Tooltip: m_Pos: serializedVersion: 2 - x: 629 - y: 570 - width: 255 - height: 429 + x: 485 + y: 668 + width: 394 + height: 331 m_SerializedDataModeController: m_DataMode: 0 m_PreferredDataMode: 0 @@ -1260,9 +1260,9 @@ MonoBehaviour: m_Tooltip: m_Pos: serializedVersion: 2 - x: 886 + x: 881 y: 73 - width: 412 + width: 453 height: 926 m_SerializedDataModeController: m_DataMode: 0 @@ -1285,7 +1285,7 @@ MonoBehaviour: m_SkipHidden: 0 m_SearchArea: 2 m_Folders: - - Assets/Art + - Packages/com.alicizax.unity.framework/Runtime/Localization m_Globs: [] m_OriginalText: m_ImportLogFlags: 0 @@ -1301,7 +1301,7 @@ MonoBehaviour: scrollPos: {x: 0, y: 0} m_SelectedIDs: e48c0000 m_LastClickedID: 36068 - m_ExpandedIDs: 000000007e020000666a0000686a00006a6a00006c6a00006e6a0000706a0000726a0000746a0000766a0000786a00007a6a00007c6a00007e6a0000806a0000826a0000846a0000866a0000886a00008a6a00008c6a00008e6a0000906a0000926a0000946a0000966a0000986a00009a6a00009c6a00009e6a0000a06a0000a26a0000a46a0000a66a0000a86a0000aa6a0000ac6a0000ae6a0000b06a0000b26a0000b46a0000b66a0000b86a0000ba6a0000bc6a0000be6a0000c06a0000c26a0000c46a0000c66a0000c86a0000ca6a0000cc6a0000ce6a0000d06a0000d26a0000d46a0000d66a0000d86a0000da6a0000dc6a0000de6a0000e06a0000e26a0000e46a0000e66a0000e86a0000ea6a0000ec6a0000ee6a0000f06a0000f26a0000f46a0000f66a0000f86a0000 + m_ExpandedIDs: 000000007e020000fe0c0000606a0000626a0000646a0000666a0000686a00006a6a00006c6a00006e6a0000706a0000726a0000746a0000766a0000786a00007a6a00007c6a00007e6a0000806a0000826a0000846a0000866a0000886a00008a6a00008c6a00008e6a0000906a0000926a0000946a0000966a0000986a00009a6a00009c6a00009e6a0000a06a0000a26a0000a46a0000a66a0000a86a0000aa6a0000ac6a0000ae6a0000b06a0000b26a0000b46a0000b66a0000b86a0000ba6a0000bc6a0000be6a0000c06a0000c26a0000c46a0000c66a0000c86a0000ca6a0000cc6a0000ce6a0000d06a0000d26a0000d46a0000d66a0000d86a0000da6a0000dc6a0000de6a0000e06a0000e26a0000e46a0000e66a0000e86a0000ea6a0000ec6a0000ee6a0000f06a0000f26a0000f46a0000f66a0000f86a0000 m_RenameOverlay: m_UserAcceptedRename: 0 m_Name: @@ -1326,21 +1326,21 @@ MonoBehaviour: m_Icon: {fileID: 0} m_ResourceFile: m_AssetTreeState: - scrollPos: {x: 0, y: 0} + scrollPos: {x: 0, y: 580} m_SelectedIDs: m_LastClickedID: 0 - m_ExpandedIDs: ffffffff000000007e020000040d0000666a0000686a00006a6a00006c6a0000706a0000726a0000746a0000766a0000786a00007a6a00007c6a00007e6a0000806a0000826a0000846a0000866a0000886a00008a6a00008c6a00008e6a0000906a0000926a0000946a0000986a00009a6a00009c6a00009e6a0000a06a0000a26a0000a46a0000a66a0000a86a0000aa6a0000ac6a0000ae6a0000b06a0000b26a0000b46a0000b66a0000b86a0000ba6a0000bc6a0000be6a0000c06a0000c26a0000c46a0000c66a0000c86a0000ca6a0000cc6a0000ce6a0000d06a0000d26a0000d46a0000d66a0000d86a0000da6a0000de6a0000e26a0000ea6a0000ee6a0000f26a0000f46a0000f66a0000f86a0000ba6c0000ea6c0000ee6c0000146d00002a6d0000426d0000946e0000966e0000cc6e00006a7600007076000074760000ffffff7f + m_ExpandedIDs: ffffffff000000007e020000fe0c0000606a0000626a0000646a0000666a0000686a00006a6a00006c6a0000706a0000726a0000746a0000766a0000786a00007a6a00007c6a00007e6a0000806a0000826a0000846a0000866a0000886a00008a6a00008c6a00008e6a0000906a0000926a0000946a0000966a0000986a00009a6a00009c6a00009e6a0000a06a0000a26a0000a46a0000a66a0000a86a0000aa6a0000ac6a0000ae6a0000b06a0000b26a0000b46a0000b66a0000b86a0000ba6a0000bc6a0000c06a0000c26a0000c46a0000c66a0000c86a0000ca6a0000cc6a0000d06a0000d26a0000d46a0000d66a0000d86a0000da6a0000dc6a0000e66a0000e86a0000ea6a0000ec6a0000ee6a0000f06a0000f26a0000f66a0000f86a0000ee6c0000fc6c00003a6d0000267500002a750000367500007c77000090770000ffffff7f m_RenameOverlay: m_UserAcceptedRename: 0 - m_Name: UILoadUpdateWindow - m_OriginalName: UILoadUpdateWindow + m_Name: ObjectPoolSystemDesign + m_OriginalName: ObjectPoolSystemDesign m_EditFieldRect: serializedVersion: 2 x: 0 y: 0 width: 0 height: 0 - m_UserData: 27900 + m_UserData: 11722 m_IsWaitingForDelay: 0 m_IsRenaming: 0 m_OriginalEventType: 0 @@ -1405,9 +1405,9 @@ MonoBehaviour: m_Tooltip: m_Pos: serializedVersion: 2 - x: 1300 + x: 1336 y: 73 - width: 619 + width: 583 height: 926 m_SerializedDataModeController: m_DataMode: 0