一个常驻 Editor 监控端 + 一个 Development Player + 一个外部 AI 分析进程。 Player 侧尽量不动,只保留 Unity 自带远程 Profiler 能力;尖峰检测、抓帧、解析、调用 AI 全放在 Editor 侧。 可行性判断 可行,前提是: - Player 必须是 Development Build - 关闭 Autoconnect Profiler,改成手动 Attach to Player - 不开 Deep Profiling Support - 监控期间必须有一个 Unity Editor 进程连着这个 Player Unity 2022.3 官方文档明确: - 手动 Attach to Player 只有在 Autoconnect Profiler 关闭时才可用 - 远程 profiling 的前提是目标在运行 Development Build - ProfilerWindow / RawFrameDataView / HierarchyFrameDataView 都是 Editor 侧能力 来源: - https://docs.unity3d.com/cn/2022.3/Manual/profiler-profiling-applications.html - https://docs.unity3d.com/cn/2022.1/ScriptReference/ProfilerWindow.html - https://docs.unity3d.com/ja/2022.3/ScriptReference/Profiling.RawFrameDataView.html 推荐架构 1. 构建层 - 只开 Development Build - 不开 Autoconnect Profiler - 不开 Deep Profiling Support 这样 Player 侵入最低,也保留手动远程 attach 能力。 你们现有入口里,client/Assets/Scripts/Editor/Builder/AndroidAppBuilder.cs:92 和 client/Assets/Scripts/Editor/Builder/WindowAppBuilder.cs:43 都可以拆一个专门的 ProfileBuild 配置。 2. 连接层 - 启动 Player - 在常驻 Editor 中手动 Attach to Player - 一旦连上,后面监控逻辑自动跑 这里我建议第一版不要做“自动 attach”。 原因是“编程方式切换 Active Profiler 连接”公开 API 很弱,强行自动化通常要碰 UnityEditorInternal / 反射,升级风险高。 第一版只要求人工选一次连接,后面全部自动。 3. 监控层 - Editor 里做一个 EditorWindow 或 [InitializeOnLoad] 服务 - 持续盯 ProfilerWindow.lastAvailableFrameIndex - 每来一个新 frame,就读该 frame 的 CPU 时间 - 超过阈值就进入分析流程 这里可以直接基于 ProfilerWindow 的最新帧索引做,不需要 Player 回传 frameIndex。 ProfilerWindow 提供 lastAvailableFrameIndex 和 selectedFrameIndex。 来源:https://docs.unity3d.com/cn/2022.1/ScriptReference/ProfilerWindow.html 4. 解析层 - 对触发帧用 HierarchyFrameDataView 拿主线程/渲染线程热点树 - 取 Top N 热点 sample - 对重点 sample 再用 RawFrameDataView 深挖 - 抽: - frameTimeMs - frameGpuTimeMs - 主线程 Top N - RenderThread Top N - GC.Alloc - Unity Object 信息 - 可用 callstack FrameDataView 里直接有 frameTimeMs / frameGpuTimeMs 等帧级信息。 RawFrameDataView 官方示例也明确支持遍历样本和查 GC.Alloc。 来源: - https://docs.unity3d.com/cn/2022.1/ScriptReference/Profiling.FrameDataView.html - https://docs.unity3d.com/ja/2022.3/ScriptReference/Profiling.RawFrameDataView.html - https://docs.unity3d.com/cn/2022.3/ScriptReference/Profiling.FrameDataView.GetUnityObjectInfo.html 5. AI 输入层 不要把整帧原始数据直接扔给 AI。先整理成一个紧凑 JSON,例如: { "session": { "platform": "Android", "device": "xxx", "build": "development" }, "frame": { "index": 12345, "cpuFrameMs": 68.4, "gpuFrameMs": 41.2 }, "threads": [ { "name": "Main Thread", "topSamples": [ { "name": "Canvas.SendWillRenderCanvases", "totalMs": 23.1, "selfMs": 4.2, "calls": 1 } ] } ], "gc": { "allocBytes": 524288 }, "unityObjects": [ { "type": "Texture2D", "name": "xxx" } ] } 然后再补两类上下文给 AI: - 设备、场景、操作步骤、网络状态 - 根据热点 marker 名在仓库里 rg 出来的候选代码文件 这样 AI 才能给“代码级建议”,不是只说“UI 很慢”。 第一版建议的最小闭环 我建议你先只做这条链: 1. Development Build 运行 2. Editor 手动 attach 3. Editor 自动监控最新帧 4. CPU 帧时间超阈值 5. 解析主线程 Top 10 + RenderThread Top 5 + GC.Alloc 6. 生成 spike-report.json 7. 拉起外部 AI CLI 分析 先不要做: - 自动 attach - 全模块分析 - Deep Profiling - Player 侧埋点改造 - 自动改代码 关键风险 - 远程 attach 本身就有开销,所以阈值要留冗余,不能拿它当“最终真实性能数据”。 - 不开 Deep Profiling 时,很多热点只能看到 Unity marker,看不到足够细的业务方法。 - 如果没有你们自己的 ProfilerMarker,AI 很可能只能把建议停留在“怀疑某个 UI 刷新或资源加载链路”。 所以这套方案第一阶段的价值更像: - 自动发现尖峰 - 自动归档证据 - 自动把“热点帧 -> 代码候选 -> 优化建议”串起来 不是一步到位做根因精确定位。 我对落地顺序的建议 1. 先做 Editor 监控器 2. 再做帧解析导出 JSON 3. 再接 AI CLI 4. 最后再考虑自动 attach 和自定义 marker