Unity Skill
When to use
- Creating or modifying Unity scenes, prefabs, or C# MonoBehaviour scripts
- Choosing between URP, HDRP, or Built-in render pipeline
- Designing game systems (input, audio, UI, save/load, pooling)
- Profiling and fixing frame-rate drops, GC spikes, or memory pressure
- Setting up CI builds (Unity Build Automation / GitHub Actions) for multiple platforms
- Preparing a build for Steam, iOS App Store, Google Play, or console certification
Workflow
- Confirm Unity version and render pipeline — check
ProjectSettings/ProjectVersion.txtand the active render pipeline asset. URP for mobile/cross-platform, HDRP for high-fidelity PC/console, Built-in only for legacy projects. Do not switch pipeline mid-project without a full asset migration plan. - Project structure — establish before adding content:
Assets/ _Project/ # All project-specific assets (underscore sorts first) Art/ Audio/ Prefabs/ Scenes/ Scripts/ ScriptableObjects/ Settings/ ThirdParty/ # Package Store assets, unmodified Packages/ # Unity Package Manager entries (packages.json) - Scene and prefab discipline:
- One scene per major gameplay state (MainMenu, Gameplay, Loading)
- Use Additive scene loading for streaming large worlds
- Nest prefabs rather than duplicating GameObjects; never duplicate a prefab's contents across scenes
- Mark prefab variant overrides intentionally; unintended overrides break batch updates
- C# scripting patterns:
- Prefer
ScriptableObjectfor shared configuration and game-wide events (Event Channel pattern) over singletons - Use the Service Locator or Zenject/VContainer for DI instead of
FindObjectOfTypein production code - Reserve
MonoBehaviourfor things that genuinely belong on a GameObject; move pure logic to plain C# classes - Cache component references in
Awake; never callGetComponentinsideUpdate
- Prefer
- Input: use the new Input System (
com.unity.inputsystem) with anInputActionAsset; generated C# wrapper class per action map. AvoidInput.GetKeyin new code. - Object pooling: use
UnityEngine.Pool.ObjectPool<T>(Unity 2021+) for bullets, VFX, and any frequently instantiated/destroyed objects.Instantiate/DestroyinUpdateat high frequency causes GC pressure. - UI: use UI Toolkit (USS + UXML) for complex runtime UI on supported platforms; use uGUI (Canvas) for world-space UI or when targeting older Unity versions. Never mix UI Toolkit runtime and uGUI in the same panel hierarchy.
- Audio: use Unity's Audio Mixer with exposed parameters for dynamic mixing; load audio clips as
Streamingfor music andDecompressOnLoadonly for short, frequently-played SFX. - Profiling pass (before each milestone):
- Open Profiler (
Window → Analysis → Profiler); record on a target device, not in Editor - Check CPU: identify
Update/FixedUpdatehot paths; eliminate per-frame allocations shown in GC Alloc column - Check Memory: use Memory Profiler package; look for duplicate textures and leaked assets
- Check Rendering: use Frame Debugger to identify overdraw and unnecessary draw calls; use GPU Instancing for repeated meshes
- Target: ≥30 fps sustained on the minimum-spec device; <2 ms GC spikes per frame
- Open Profiler (
- Build pipeline:
- Use Build Profiles (
BuildProfileasset, Unity 6) orBuildPlayerOptionsscripting for automated builds - Strip unused code: enable
Managed Stripping Level: Highwith alink.xmlto protect reflected types - IL2CPP is required for iOS and recommended for Android release; verify with Mono first in dev, IL2CPP before final QA
- Never commit
Library/,Temp/,Logs/, or.DS_Store— add to.gitignorebefore first commit
- Use Build Profiles (
Standards
| Area | Do | Do not |
|---|---|---|
| Scene references | Assign references in the Inspector via serialized fields | GameObject.Find or FindObjectOfType at runtime |
| Data | ScriptableObject for config, balancing data, and event channels |
static fields for cross-object communication |
| Allocations | Pool reusable objects; use StringBuilder for string concatenation in hot paths |
new in Update; string concatenation with + per frame |
| Physics | Use layer-based collision matrix to limit Physics.FixedUpdate work |
Physics.OverlapSphere with no layer mask in a tight loop |
| Coroutines | Use for time-based sequences; cache WaitForSeconds instances |
Start coroutines that are never stopped on a frequently-created object |
| Async | UniTask (or Awaitable in Unity 6) for async/await; never block main thread |
Thread.Sleep or blocking I/O on main thread |
| Assets | Mark textures with correct compression per platform (ASTC for mobile) | Leave all textures at RGBA32 default for all platforms |
Common mistakes to avoid
- Serialized field left null in prefab — Unity does not throw on null serialized references at edit time. Add
[SerializeField][NotNull]validation or null-check inAwakewith a clear error message. - Modifying
TransforminsideFixedUpdatewithout Rigidbody — causes physics jitter. UseRigidbody.MovePosition/MoveRotationor setTransformonly inUpdatewithTime.deltaTimescaling. Resources.Loadoveruse —Resourcesfolder disables asset stripping and bloats build size. Use Addressables for runtime-loaded assets.- GC spikes from
foreachon Unity collections —foreachonList<T>is fine;foreachonDictionary<K,V>or custom Unity collections allocates an enumerator. Useforloops or cache the enumerator. - Physics layer matrix not configured — every layer collides with every other layer by default, which multiplies physics work. Configure the collision matrix in
Project Settings → Physicsbefore adding gameplay layers. - Scene not added to Build Settings —
SceneManager.LoadScene("SceneName")silently fails at runtime if the scene is not in the Build Settings list. Add scenes as part of the PR that creates them. DontDestroyOnLoadproliferation — creating multiple manager singletons withDontDestroyOnLoadleads to duplicate instances after scene reloads. Use a singleGameManageror a DI container to control lifetime.
Output format
Typical feature deliverable structure:
Assets/_Project/
Scripts/
<Feature>/
<Feature>System.cs # Core logic as plain C# class (no MonoBehaviour)
<Feature>Controller.cs # MonoBehaviour; thin, delegates to System
<Feature>Config.cs # ScriptableObject with [CreateAssetMenu]
<Feature>Events.cs # ScriptableObject event channels (raise/listen)
Prefabs/
<Feature>/
<Feature>Prefab.prefab
Scenes/
<Feature>Scene.unity # If a dedicated scene is required
ScriptableObjects/
<Feature>/
<Feature>DefaultConfig.asset
Tests/
EditMode/
<Feature>SystemTests.cs # NUnit tests for pure C# logic
PlayMode/
<Feature>IntegrationTests.cs # Tests requiring MonoBehaviour/scene context
Related checklists
.claude/checklists/performance.md.claude/checklists/security.md.claude/checklists/production.md
Related agents
.claude/agents/stack/game/unity-engineer.md.claude/agents/engineering/game-engineer.md.claude/agents/domain/gaming-domain-expert.md.claude/agents/design/game-ux-specialist.md.claude/agents/quality/performance-engineer.md