协作头脑风暴
brainstorming
在实现前澄清需求、探索设计选择,并形成清晰的开发方向。
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…
独立 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.
unity-core); pipeline
selection (use unity-rendering).
allowed-tools: Read, Grep, Glob, Write, EditMake a Development Build with Autoconnect Profiler + Deep Profiling Support. Don't profile editor — numbers are misleading.
Common culprits:
| Cause | Fix |
|---|---|
string concatenation in Update | StringBuilder reused, or only build when value changes |
List<T>.ToArray() per frame | Cache list, reuse |
foreach over some collections (boxing) | for loop over IList<T> |
GetComponent in Update | Cache in Awake |
LINQ (.Where, .Select) per frame | Manual loops |
| Lambda capturing locals | Convert to method or pre-allocate delegate |
Read GC Alloc column in Profiler hierarchy — anything > 0 in Update is suspect.
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.
[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.
link.xml for reflection-only types.| Technique | When |
|---|---|
| Static Batching | Mark static + same material → bake at build |
| Dynamic Batching | Auto for very small meshes; off in URP by default |
| GPU Instancing | Same mesh + same shader, slight per-instance variation via MaterialPropertyBlock |
| SRP Batcher | URP/HDRP default — same shader variant batched into one SetPass |
| GPU Resident Drawer (Unity 6) | Auto-instancing for static objects with shared mesh+mat |
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-pattern | Fix |
|---|---|
| Profiling editor numbers | Profile Development Build only |
Camera.main per frame | Cache once |
new Vector3(...) in Update with constants | Make static readonly |
transform.GetChild(i).gameObject repeatedly | Cache child references |
Per-frame string.Format for HUD text | Update only on value change |
| Profiler with deep profile shipped to QA | Only enable for short investigations |