인터페이스는 현지화되어 있으며, Skill 소개와 설명 문서는 선택한 언어로 AI가 자동 번역합니다. 코드·명령어·경로·전문 용어는 원문을 유지하며 원작자 문서가 우선합니다.
Skills 둘러보기
개발 및 엔지니어링 · SKILL.md

unity-performance

unity-performance

Unity performance — Profiler, Frame Debugger, Memory Profiler, GC allocation hunting, object pooling, IL2CPP build settings, Burst, batching, LOD, GPU Resident Drawer. USE WHEN: frame drops, GC spikes, long load times, memory growth, draw-call storms, mobile thermal/battery issues, profiling captures. DO NOT USE FOR: gameplay logic refactoring (use `unity…

Independent GitHub snapshot · Automated classification · Original documentation governs

Skill 문서

GitHub

name: unity-performance description: | Unity performance — Profiler, Frame Debugger, Memory Profiler, GC allocation hunting, object pooling, IL2CPP build settings, Burst, batching, LOD, GPU Resident Drawer.

USE WHEN: frame drops, GC spikes, long load times, memory growth, draw-call storms, mobile thermal/battery issues, profiling captures.

DO NOT USE FOR: gameplay logic refactoring (use unity-core); pipeline selection (use unity-rendering). allowed-tools: Read, Grep, Glob, Write, Edit

Unity Performance

Tools

  • Profiler (Window > Analysis > Profiler): CPU / GPU / Memory / Rendering / Audio / Physics.
  • Frame Debugger (Window > Analysis > Frame Debugger): step through draw calls, see batching breaks.
  • Memory Profiler package: snapshots, diff, find leaks.
  • Profile Analyzer package: aggregate frames across captures.
  • Use Deep Profile sparingly — adds overhead but shows method-level hotspots.

Build for profiling

Make a Development Build with Autoconnect Profiler + Deep Profiling Support. Don't profile editor — numbers are misleading.

GC allocation hunting

Common culprits:

CauseFix
string concatenation in UpdateStringBuilder reused, or only build when value changes
List<T>.ToArray() per frameCache list, reuse
foreach over some collections (boxing)for loop over IList<T>
GetComponent in UpdateCache in Awake
LINQ (.Where, .Select) per frameManual loops
Lambda capturing localsConvert to method or pre-allocate delegate

Read GC Alloc column in Profiler hierarchy — anything > 0 in Update is suspect.

Object pooling

private readonly IObjectPool<Bullet> _pool = new ObjectPool<Bullet>(
    createFunc:    () => Object.Instantiate(prefab),
    actionOnGet:   b => b.gameObject.SetActive(true),
    actionOnRelease: b => b.gameObject.SetActive(false),
    actionOnDestroy: Object.Destroy,
    defaultCapacity: 32, maxSize: 256);

public void Fire() {
    var b = _pool.Get();
    b.transform.position = muzzle.position;
    b.OnExpired = () => _pool.Release(b);
}

UnityEngine.Pool.ObjectPool<T> since Unity 2021.1. For SO-driven pools or ECS, use NativeArray-backed structures.

Burst + Jobs

[BurstCompile]
public struct ApplyGravityJob : IJobParallelFor {
    public NativeArray<float3> Velocities;
    public float DeltaTime;
    public void Execute(int i) {
        Velocities[i] += new float3(0, -9.81f * DeltaTime, 0);
    }
}

void Update() {
    var job = new ApplyGravityJob { Velocities = _velocities, DeltaTime = Time.deltaTime };
    var handle = job.Schedule(_velocities.Length, 64);
    handle.Complete();
}

Burst compiles to highly optimized native; works only on struct jobs with NativeArray/blittable types.

IL2CPP build settings

  • IL2CPP Code Generation: "Faster runtime" for shipping; "Faster (smaller) builds" for iteration.
  • Managed Stripping Level: Low/Medium for safety; High only with thorough QA + link.xml for reflection-only types.
  • Engine Code Stripping: enable to drop unused subsystems.

Batching & instancing

TechniqueWhen
Static BatchingMark static + same material → bake at build
Dynamic BatchingAuto for very small meshes; off in URP by default
GPU InstancingSame mesh + same shader, slight per-instance variation via MaterialPropertyBlock
SRP BatcherURP/HDRP default — same shader variant batched into one SetPass
GPU Resident Drawer (Unity 6)Auto-instancing for static objects with shared mesh+mat

LOD

LOD 0 = full mesh (close)
LOD 1 = half tris (medium)
LOD 2 = quarter tris (far)
LOD 3 = imposter or culled

Use LODGroup with screen-relative transition heights. Combine with Occlusion Culling for indoors.

Anti-patterns

Anti-patternFix
Profiling editor numbersProfile Development Build only
Camera.main per frameCache once
new Vector3(...) in Update with constantsMake static readonly
transform.GetChild(i).gameObject repeatedlyCache child references
Per-frame string.Format for HUD textUpdate only on value change
Profiler with deep profile shipped to QAOnly enable for short investigations

Production checklist

  • Frame budget hit on target devices (e.g. 16ms PC, 33ms mobile)
  • GC alloc per frame ≤ ~0 in steady state
  • Object pools for bullets/VFX/UI fly-outs
  • Burst-compiled jobs for hot math
  • LODGroup + Occlusion Culling tuned
  • Shader variants pre-warmed
  • Memory snapshot baseline + post-soak captured & diffed
저장한 Skills