mcpField
U
unity-performance

unity-performance

github.com/besty0728Development1.9k84 installsUpdated today
Repository

About unity-performance

unity-performance is a Unity code-review skill for developers investigating frame drops, allocations, and optimization choices. It prioritizes concrete performance red flags and separates likely issues from speculative micro-optimizations.

Key features

  1. 01Flags costly per-frame lookups and update loops
  2. 02Identifies allocation and pooling candidates
  3. 03Explains hidden runtime costs
  4. 04Organizes findings by confidence and impact

Use cases

  1. 01Reviewing Unity code for performance risks
  2. 02Investigating frame drops or stutter
  3. 03Planning object pooling and allocation reduction

Install

Copy the command and run it in a terminal.

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

After installing, type/unity-performancein Claude Code to confirm it loaded.

Details

From the project README

Before calling any skill in this module: if you are about to call a skill with parameters guessed from its name or description, STOP — read this file (or fetch its schema via GET /skills/recommend?includeSchema=true) first. If you already have the parameter definitions from recommend/schema, you may proceed straight to dryRun.

Triggers

  • Reviewing performance
  • Diagnosing frame drops
  • Reducing allocations
  • Planning pooling/optimization
  • 做性能审查、诊断掉帧或卡顿、减少内存分配、规划对象池/优化

Unity Performance Red Flags

Use this skill for a high-signal review of likely Unity performance issues. Focus on red flags, not speculative micro-optimizations.

Check For

  • Too many unrelated Update / LateUpdate / FixedUpdate loops
  • Repeated Find, GetComponent, Camera.main, or tag lookups in hot paths
  • Frequent Instantiate / Destroy suitable for pooling
  • Avoidable per-frame allocations:
    • LINQ
    • string formatting
    • closures
    • boxing
  • Reflection in runtime hot paths
  • Expensive editor-only helpers leaking into runtime code
  • Physics, animation, or UI updates happening at the wrong cadence

Hidden Costs: Possibility ≠ Actuality

Three counter-intuitive traps where what seems "free" is actually expensive. Each cost is paid for possibility of work, not for work actually performed — which is why profilers rarely catch them directly.

Write permission costs, even without writing

A component whose Update can mutate transform.position pays the cost whether the branch runs or not: dirty-flag and serialization systems treat write permission as a reason to poll every frame. Similarly, a [SerializeField] field that is never modified at runtime still sits on the serialization path. The fix is to remove the permission, not tighten the branch — split the rarely-needed writer into its own component and AddComponent only when needed. Source: NetcodeSamples/HelloNetcode/2_Intermediate/07_Optimization/Optimization.md — "a system with the possibility of writing to a component, regardless of whether it writes to it or not, will always have to be serialized".

Sequential seeds produce correlated random streams

Seeding N RNG instances with baseSeed + i gives N similar streams — patrol paths line up, spawn jitter clumps, loot rolls cluster. Hash the index before seeding:

// 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) applies this internally and is preferred when the math package is available. Source: Dots101/Entities101/Assets/HelloCube/3. Prefabs/SpawnSystem.cs:37-39 and its comment.

Logging fires in release builds by default

Debug.Log is not stripped in Player builds; only methods marked [Conditional("UNITY_EDITOR")] (such as Debug.DrawLine) have their arguments elided at the call site. That means a log line with interpolation or helper calls runs every frame in shipped games:

// 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}");

The same principle as the "possibility write" rule above — the runtime pays for the possibility of work, not only for the work.

Output Format

  • Confirmed red flags
  • Likely red flags
  • Changes worth doing now
  • Changes not worth doing now
  • Expected gain category: clarity / frame time / GC / scalability

Guardrails

Mode: Documentation only — no REST skills to gate; load freely under any operating mode (Approval / Auto / Bypass).

  • Do not recommend large refactors without a meaningful hotspot.
  • Do not replace simple code with unreadable “optimized” code unless the hot path is real.

Comments

Markdown supported