mcpField
U
unity-performance

unity-performance

github.com/besty0728开发1.9k84 次安装今天更新
代码仓库

关于 unity-performance

unity-performance 面向 Unity 开发者,用于排查掉帧、内存分配和优化问题。它聚焦明确的性能风险,并区分可能的问题与缺乏依据的微优化。

主要功能

  1. 01标记高频查找和更新循环
  2. 02识别分配与对象池机会
  3. 03说明不易察觉的运行时开销
  4. 04按确定性和影响整理发现

适用场景

  1. 01审查 Unity 代码的性能风险
  2. 02调查掉帧或卡顿
  3. 03规划对象池和减少内存分配

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/besty0728/unity-skills --skill unity-performance

安装后在 Claude Code 中输入/unity-performance确认已加载。

详细介绍

**调用本模块中的任何技能前:**如果你打算根据技能名称或描述猜测参数后调用技能,请停下——先阅读此文件(或通过 GET /skills/recommend?includeSchema=true 获取其架构)。如果你已从 recommend/schema 获得参数定义,可以直接进行 dryRun。

触发条件

  • 审查性能
  • 诊断掉帧
  • 减少内存分配
  • 规划对象池/优化
  • 做性能审查、诊断掉帧或卡顿、减少内存分配、规划对象池/优化

Unity 性能风险信号

使用此技能,对可能存在的 Unity 性能问题进行高信号审查。重点关注风险信号,而非推测性的微优化。

检查项

  • 过多互不相关的 Update / LateUpdate / FixedUpdate 循环
  • 在热点路径中重复调用 Find、GetComponent、Camera.main 或标签查找
  • 频繁执行适合使用对象池的 Instantiate / Destroy
  • 可避免的逐帧内存分配:
    • LINQ
    • 字符串格式化
    • 闭包
    • 装箱
  • 运行时热点路径中的反射
  • 泄漏到运行时代码中的高开销编辑器专用辅助工具
  • 物理、动画或 UI 更新发生在不合适的频率

隐性开销:可能性 ≠ 实际开销

有三个反直觉的陷阱:看似“免费”,实际上却代价高昂。每项开销都是为工作可能发生而付出的,而非为实际执行的工作付出——这就是性能分析器很少能直接捕获它们的原因。

即使不写入,也要为写入权限付出代价

即使分支从未执行,只要组件的 Update 可能修改 transform.position,就要付出代价:脏标记和序列化系统会把写入权限视为需要逐帧轮询的理由。同样,运行时从未修改的 [SerializeField] 字段仍处于序列化路径上。解决方法是移除写入权限,而不是收紧分支——将很少需要的写入逻辑拆分到独立组件中,仅在需要时才 AddComponent。来源:NetcodeSamples/HelloNetcode/2_Intermediate/07_Optimization/Optimization.md — “无论是否实际写入,只要系统有可能写入某个组件,就始终必须对其进行序列化”。

顺序种子会产生相关的随机流

使用 baseSeed + i 为 N 个 RNG 实例设种子,会得到 N 个相似的随机流——巡逻路线会重合,生成抖动会聚集,战利品结果会成簇。设种子前先对索引进行哈希:

// Wrong — N correlated streams
for (int i = 0; i < N; i++) rngs[i] = new System.Random(baseSeed + i);

// Correct — hash decorrelates adjacent seeds
for (int i = 0; i < N; i++)
    rngs[i] = new System.Random((int)((uint)baseSeed * 2654435761u ^ (uint)i));

Unity.Mathematics.Random.CreateFromIndex(i) 会在内部执行此操作;如果可使用数学包,优先采用此方法。来源:Dots101/Entities101/Assets/HelloCube/3. Prefabs/SpawnSystem.cs:37-39 及其注释。

默认情况下,发布版本也会执行日志记录

Player 构建中不会剔除 Debug.Log;只有标记了 [Conditional("UNITY_EDITOR")] 的方法(例如 Debug.DrawLine)才会在调用位置省略其参数。这意味着,已发布游戏中的日志行若包含插值或辅助方法调用,就会逐帧运行:

// Wrong — GetPlayerInfo() and string interpolation execute in release
Debug.Log($"Player {GetPlayerInfo()} at {Time.time}");

// Better — guard the whole expression
if (Debug.isDebugBuild) Debug.Log($"Player {GetPlayerInfo()} at {Time.time}");

这与上文“写入可能性”规则遵循同一原则——运行时要为工作可能发生付出代价,而不仅仅是为实际执行的工作付出代价。

输出格式

  • 已确认的风险信号
  • 可能存在的风险信号
  • 值得立即进行的更改
  • 当前不值得进行的更改
  • 预期收益类别:清晰度 / 帧时间 / GC / 可扩展性

注意事项

模式:仅限文档——无需 REST 技能进行门控;任何操作模式(Approval / Auto / Bypass)下均可自由加载。

  • 没有显著的热点时,不要建议进行大型重构。
  • 除非确实存在热点路径,否则不要用难以阅读的“优化”代码替换简单代码。

评论

支持 Markdown