Unity Engine
C# architecture, the component/data models, performance patterns, and rendering choices for Unity 6.x (the unified successor to 2022 LTS / 2023).
When to Use
- Writing C# gameplay with the
MonoBehaviour lifecycle and a component-based architecture.
- Structuring data and config with prefabs and ScriptableObjects.
- Handling input via the Input System package (action maps), not the legacy
Input manager.
- Choosing coroutines vs async/await, and avoiding per-frame allocations / GC spikes.
- Loading assets with Addressables (and getting off direct
Resources/hard references).
- Going data-oriented: DOTS/ECS, the Job System, and Burst for heavy simulation.
- Picking and configuring a render pipeline: URP (broad/mobile) vs HDRP (high-end).
Do not use
| If the task is… |
Use instead |
| Turning a raw idea into a Unity plan with AI-generated assets/prompts |
unity-ai-game-creator |
| Unreal Engine C++/Blueprints |
game-unreal-engine |
| Godot 4.x |
game-godot-master |
| Authoring/exporting meshes & rigs in Blender |
game-blender-asset-pipeline |
| FMOD/Wwise middleware |
game-fmod-wwise-integration |
| App Store/Play IAP, ads, Game Center |
game-mobile-store-integration |
unity-ai-game-creator is an AI-asset workflow wrapper (idea → roadmap → generation prompts). This skill is the engine reference: how Unity actually executes, and the C#/architecture patterns that hold up in production.
Prerequisites
- Unity 6.x installed (or Unity 2022 LTS / 2023 with compatible APIs). Confirm version in
ProjectSettings/ProjectVersion.txt.
- C# 9.0+ support (default in Unity 6). For
Awaitable, Unity 6 is required; on older versions use UniTask.
- Input System package installed:
Window → Package Manager → Input System (version 1.7+).
- Addressables package installed:
Window → Package Manager → Addressables (version 2.x+ for Unity 6).
- Burst and Collections packages installed if using Job System / DOTS.
- Render pipeline package installed:
Universal RP for URP, High Definition RP for HDRP.
- Windows host is primary (PowerShell). Paths use backslashes on Windows; forward slashes on macOS/Linux.
Procedure
1. MonoBehaviour lifecycle — know the order
| Callback |
When |
Use for |
Awake |
On instantiation, before any Start |
Self-setup, cache GetComponent — no cross-object refs yet |
OnEnable |
Each time the object enables |
Subscribe to events |
Start |
Before first frame, after all Awakes |
Cross-object wiring (others are now awake) |
FixedUpdate |
Fixed physics step |
All physics — forces, Rigidbody moves |
Update |
Every frame |
Input, game logic, non-physics |
LateUpdate |
After all Updates |
Camera follow, post-movement adjustments |
OnDisable/OnDestroy |
Disable/teardown |
Unsubscribe, release |
Rule: read input in Update, move rigidbodies in FixedUpdate, follow with the camera in LateUpdate. Mixing these causes jitter and missed input.
public class PlayerController : MonoBehaviour
{
private Rigidbody _rb;
private Vector2 _moveInput;
void Awake()
{
_rb = GetComponent<Rigidbody>(); // cache once
}
void OnEnable() => InputManager.OnMove += HandleMove;
void OnDisable() => InputManager.OnMove -= HandleMove;
void HandleMove(Vector2 dir) => _moveInput = dir;
void FixedUpdate()
{
// Physics moves belong here — fixed timestep, deterministic.
_rb.linearVelocity = new Vector3(_moveInput.x, 0f, _moveInput.y) * 5f;
}
}
2. Component & data architecture
// ScriptableObject: shared, designer-tunable data — one asset, referenced by many.
[CreateAssetMenu(menuName = "Game/EnemyDef")]
public class EnemyDef : ScriptableObject
{
public float maxHealth = 100f;
public float moveSpeed = 3f;
public GameObject prefab;
}
- Prefer composition (small components) over deep
MonoBehaviour inheritance.
- Put shared config in ScriptableObjects, not duplicated across prefab instances — one source of truth, no per-instance drift, and they're editable without touching scenes.
- ScriptableObjects also make clean event channels and runtime sets, decoupling systems that shouldn't reference each other directly.
// Event channel pattern — decoupled raise/listen.
[CreateAssetMenu(menuName = "Game/FloatEvent")]
public class FloatEventChannel : ScriptableObject
{
private System.Action<float> _onRaised;
public void Raise(float value) => _onRaised?.Invoke(value);
public void Register(System.Action<float> handler) => _onRaised += handler;
public void Deregister(System.Action<float> handler) => _onRaised -= handler;
}
3. Performance: allocations & GC
// BAD: allocates every frame -> GC spikes -> frame hitches.
void Update() {
var hits = Physics.OverlapSphere(transform.position, 5f); // new array each call
foreach (var go in FindObjectsOfType<Enemy>()) { /* ... */ } // very expensive
}
// GOOD: non-alloc API + cached refs + pooling.
readonly Collider[] _buf = new Collider[16];
void Update() {
int n = Physics.OverlapSphereNonAlloc(transform.position, 5f, _buf);
for (int i = 0; i < n; i++) { /* ... */ }
}
- Never call
Find/GetComponent/FindObjectsOfType in Update — cache references in Awake/Start.
- Pool bullets, enemies, VFX with the built-in
ObjectPool<T> (or your own) instead of Instantiate/Destroy churn.
- Prefer NonAlloc physics queries and
structs/cached buffers in hot paths; boxing and per-frame new feed the GC and cause stutter.
- Avoid
string concatenation and LINQ in hot loops.
// Object pooling with UnityEngine.Pool.
using UnityEngine.Pool;
public class BulletPool : MonoBehaviour
{
[SerializeField] private GameObject _bulletPrefab;
private ObjectPool<GameObject> _pool;
void Awake()
{
_pool = new ObjectPool<GameObject>(
createFunc: () => Instantiate(_bulletPrefab, transform),
actionOnGet: go => go.SetActive(true),
actionOnRelease: go => go.SetActive(false),
collectionCheck: true,
defaultCapacity: 32,
maxSize: 256);
}
public GameObject Spawn(Vector3 pos, Quaternion rot)
{
var go = _pool.Get();
go.transform.SetPositionAndRotation(pos, rot);
return go;
}
public void Despawn(GameObject go) => _pool.Release(go);
}
4. Coroutines vs async/await
- Coroutines are frame-tied (
yield return null, WaitForSeconds) and auto-stop with the GameObject — good for timed gameplay sequences.
- async/await (with
Awaitable in Unity 6 or UniTask) suits I/O, Addressables loads, and work that shouldn't be tied to a single object's lifetime — but you must cancel it (CancellationToken) when the scene/object goes away, or you touch destroyed objects.
// Coroutine — frame-tied, auto-stops with GameObject.
IEnumerator ReloadRoutine(float delay)
{
yield return new WaitForSeconds(delay);
// resume reload
}
// async/await with Awaitable (Unity 6) — must cancel on teardown.
private CancellationTokenSource _cts;
void OnEnable() => _cts = new CancellationTokenSource();
void OnDisable() => _cts?.Cancel();
async Awaitable LoadAssetAsync(string key)
{
try
{
var handle = Addressables.LoadAssetAsync<GameObject>(key);
await handle.Task.WaitAsync(_cts.Token);
// use handle.Result
}
catch (OperationCanceledException) { /* expected on teardown */ }
}
5. Addressables
- Move off hard prefab references and
Resources/ (which forces everything into the build and memory). Addressables load by address, support remote content, and let you release memory explicitly.
- Track handles and call
Addressables.Release / release the handle when done — leaked handles keep assets resident.
InstantiateAsync for spawnables; group and label assets to control what ships and downloads.
// Load, instantiate, and release correctly.
private GameObject _instance;
private AsyncOperationHandle<GameObject> _handle;
async Awaitable SpawnEnemyAsync(string address, Vector3 pos)
{
_handle = Addressables.InstantiateAsync(address, pos, Quaternion.identity);
await _handle.Task.WaitAsync(_cts.Token);
_instance = _handle.Result;
}
void DespawnEnemy()
{
if (_instance != null)
{
Addressables.ReleaseInstance(_instance);
_instance = null;
}
}
6. DOTS / ECS, Jobs, Burst
- Reach for ECS when you have thousands of similar entities (bullets, units, boids) where cache-friendly data layout and parallelism dominate. It's a different paradigm (data in components, logic in systems) — don't rewrite a small game in it for novelty.
- The C# Job System + Burst compiler parallelize and SIMD-optimize tight numeric work even without full ECS — great for procedural gen, pathfinding grids, mesh deformation.
- Don't touch
UnityEngine objects (Transforms, GameObjects) from jobs; jobs operate on NativeArray/blittable data. Use the Transform access jobs / ECS for transforms.
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
[BurstCompile]
struct VelocityJob : IJobParallelFor
{
public NativeArray<float3> positions;
[ReadOnly] public NativeArray<float3> velocities;
public float dt;
public void Execute(int i)
{
positions[i] += velocities[i] * dt; // blittable data only
}
}
// Schedule from main thread, complete before reading.
var job = new VelocityJob
{
positions = _positions,
velocities = _velocities,
dt = Time.deltaTime
};
JobHandle handle = job.Schedule(_positions.Length, 64);
handle.Complete();
7. Render pipeline choice
|
URP |
HDRP |
Built-in (legacy) |
| Target |
Mobile, Switch, broad PC, VR |
High-end PC/console |
Avoid for new projects |
| Look |
Scalable, lighter |
Film-grade, physical lights |
— |
| Cost |
Lower |
Heavy |
— |
Pick the pipeline at project start — switching later means re-authoring every material. URP is the default for most games; HDRP only when you need its high-end lighting and can afford the hardware target.
Pitfalls
GetComponent/Find in Update: cache in Awake/Start; per-frame lookups are a classic hotspot.
- Physics in
Update: rigidbody moves belong in FixedUpdate, or motion is framerate-dependent and jittery.
Instantiate/Destroy churn: pool instead; Destroy feeds the GC and fragments memory.
- Per-frame allocations: NonAlloc APIs, no LINQ/string-building in hot loops.
- Everything in
Resources/: bloats build + memory; use Addressables and release handles.
- Async work not cancelled: awaited tasks touching destroyed objects → null refs. Use CancellationToken tied to lifetime.
- Touching Unity objects from jobs: not thread-safe; jobs use NativeArrays only.
- Switching render pipeline mid-project: re-authors all materials. Decide URP vs HDRP up front.
- Deep MonoBehaviour inheritance: prefer composition + ScriptableObject data.
- Coroutines surviving scene loads: coroutines stop with their GameObject, but a
DontDestroyOnLoad host keeps them running — verify the host is cleaned up.
- ScriptableObject runtime mutation: changes to a ScriptableObject at runtime persist in the editor but not in builds. Never rely on runtime mutation for save data.
Verification
Checkable commands
# Confirm Unity project version (Windows / PowerShell).
Get-Content .\ProjectSettings\ProjectVersion.txt
# List installed packages to verify Input System, Addressables, Burst, Collections, URP/HDRP.
Get-Content .\Packages\manifest.json | Select-String "inputsystem|addressables|burst|collections|urp|hdrp"
# Check for Resources folder bloat (should be minimal or empty).
Get-ChildItem -Recurse -Directory -Filter "Resources" | Select-Object FullName
# Search codebase for per-frame anti-patterns (should return zero hits in hot paths).
Select-String -Path .\Assets\**\*.cs -Pattern "FindObjectsOfType|Find\(|GetComponent" | Where-Object { $_.Line -match "Update|FixedUpdate|LateUpdate" }
Related skills
unity-ai-game-creator — AI-driven idea→project scaffolding and asset-prompt workflow that sits on top of this engine reference.
game-unreal-engine — Cross-engine counterpart for C++/Blueprint projects.
game-blender-asset-pipeline — Authoring/exporting the meshes and rigs Unity imports.
game-fmod-wwise-integration — Middleware audio that plugs into a Unity build.
game-mobile-store-integration — IAP, ads, Game Center for Unity mobile builds.
game-steamworks-sdk — Steam integration for Unity PC builds.
References
- Unity 6 Scripting API and Manual — MonoBehaviour execution order, Input System, Addressables. Load when verifying lifecycle callbacks or Input System action map setup.
- Unity DOTS/Entities, C# Job System, and Burst documentation — Load when implementing ECS systems, scheduling jobs, or writing
[BurstCompile] code.
- Universal RP (URP) and High Definition RP (HDRP) documentation — Load when configuring render pipeline assets, volume overrides, or shader graph.
1---2name: game-unity-engine3description: Use when building games in Unity 6.x with C# — MonoBehaviour lifecycle and component architecture, prefabs and ScriptableObjects, the Input System, coroutines vs async/await, object pooling and GC-aware patterns, Addressables asset loading, DOTS/ECS and the Job System + Burst, and URP/HDRP render-pipeline choices. Triggers on Unity, MonoBehaviour, ScriptableObject, prefab, Addressables, Job System, Burst, ECS, DOTS, URP, HDRP, Awake, Start, Update, FixedUpdate, coroutine. Not for AI-prompt-driven Unity project scaffolding (use unity-ai-game-creator), Unreal (use game-unreal-engine), Godot (use game-godot-master), or Blender authoring (use game-blender-asset-pipeline).4---5
6# Unity Engine
7
8C# architecture, the component/data models, performance patterns, and rendering choices for Unity 6.x (the unified successor to 2022 LTS / 2023).
9
10## When to Use
11
12- Writing **C# gameplay** with the `MonoBehaviour` lifecycle and a component-based architecture.
13- Structuring data and config with **prefabs** and **ScriptableObjects**.
14- Handling input via the **Input System** package (action maps), not the legacy `Input` manager.
15- Choosing **coroutines vs async/await**, and avoiding per-frame allocations / GC spikes.
16- Loading assets with **Addressables** (and getting off direct `Resources`/hard references).
17- Going data-oriented: **DOTS/ECS**, the **Job System**, and **Burst** for heavy simulation.
18- Picking and configuring a render pipeline: **URP** (broad/mobile) vs **HDRP** (high-end).
19
20### Do not use
21
22| If the task is… | Use instead |
23|---|---|
24| Turning a raw idea into a Unity plan with AI-generated assets/prompts | `unity-ai-game-creator` |
25| Unreal Engine C++/Blueprints | `game-unreal-engine` |
26| Godot 4.x | `game-godot-master` |
27| Authoring/exporting meshes & rigs in Blender | `game-blender-asset-pipeline` |
28| FMOD/Wwise middleware | `game-fmod-wwise-integration` |
29| App Store/Play IAP, ads, Game Center | `game-mobile-store-integration` |
30
31`unity-ai-game-creator` is an AI-asset **workflow** wrapper (idea → roadmap → generation prompts). This skill is the **engine reference**: how Unity actually executes, and the C#/architecture patterns that hold up in production.
32
33## Prerequisites
34
35- **Unity 6.x** installed (or Unity 2022 LTS / 2023 with compatible APIs). Confirm version in `ProjectSettings/ProjectVersion.txt`.
36- **C# 9.0+** support (default in Unity 6). For `Awaitable`, Unity 6 is required; on older versions use UniTask.
37- **Input System** package installed: `Window → Package Manager → Input System` (version 1.7+).
38- **Addressables** package installed: `Window → Package Manager → Addressables` (version 2.x+ for Unity 6).
39- **Burst** and **Collections** packages installed if using Job System / DOTS.
40- Render pipeline package installed: `Universal RP` for URP, `High Definition RP` for HDRP.
41- Windows host is primary (PowerShell). Paths use backslashes on Windows; forward slashes on macOS/Linux.
42
43## Procedure
44
45### 1. MonoBehaviour lifecycle — know the order
46
47| Callback | When | Use for |
48|---|---|---|
49| `Awake` | On instantiation, before any `Start` | Self-setup, cache `GetComponent` — **no cross-object refs yet** |
50| `OnEnable` | Each time the object enables | Subscribe to events |
51| `Start` | Before first frame, after all `Awake`s | Cross-object wiring (others are now awake) |
52| `FixedUpdate` | Fixed physics step | **All physics** — forces, `Rigidbody` moves |
53| `Update` | Every frame | Input, game logic, non-physics |
54| `LateUpdate` | After all `Update`s | Camera follow, post-movement adjustments |
55| `OnDisable`/`OnDestroy` | Disable/teardown | Unsubscribe, release |
56
57**Rule:** read input in `Update`, move rigidbodies in `FixedUpdate`, follow with the camera in `LateUpdate`. Mixing these causes jitter and missed input.
58
59```csharp
60public class PlayerController : MonoBehaviour
61{
62 private Rigidbody _rb;
63 private Vector2 _moveInput;
64
65 void Awake()
66 {
67 _rb = GetComponent<Rigidbody>(); // cache once
68 }
69
70 void OnEnable() => InputManager.OnMove += HandleMove;
71 void OnDisable() => InputManager.OnMove -= HandleMove;
72
73 void HandleMove(Vector2 dir) => _moveInput = dir;
74
75 void FixedUpdate()
76 {
77 // Physics moves belong here — fixed timestep, deterministic.
78 _rb.linearVelocity = new Vector3(_moveInput.x, 0f, _moveInput.y) * 5f;
79 }
80}
81```
82
83### 2. Component & data architecture
84
85```csharp
86// ScriptableObject: shared, designer-tunable data — one asset, referenced by many.
87[CreateAssetMenu(menuName = "Game/EnemyDef")]
88public class EnemyDef : ScriptableObject
89{
90 public float maxHealth = 100f;
91 public float moveSpeed = 3f;
92 public GameObject prefab;
93}
94```
95
96- Prefer **composition** (small components) over deep `MonoBehaviour` inheritance.
97- Put **shared config in ScriptableObjects**, not duplicated across prefab instances — one source of truth, no per-instance drift, and they're editable without touching scenes.
98- ScriptableObjects also make clean **event channels** and runtime sets, decoupling systems that shouldn't reference each other directly.
99
100```csharp
101// Event channel pattern — decoupled raise/listen.
102[CreateAssetMenu(menuName = "Game/FloatEvent")]
103public class FloatEventChannel : ScriptableObject
104{
105 private System.Action<float> _onRaised;
106 public void Raise(float value) => _onRaised?.Invoke(value);
107 public void Register(System.Action<float> handler) => _onRaised += handler;
108 public void Deregister(System.Action<float> handler) => _onRaised -= handler;
109}
110```
111
112### 3. Performance: allocations & GC
113
114```csharp
115// BAD: allocates every frame -> GC spikes -> frame hitches.
116void Update() {
117 var hits = Physics.OverlapSphere(transform.position, 5f); // new array each call
118 foreach (var go in FindObjectsOfType<Enemy>()) { /* ... */ } // very expensive
119}
120
121// GOOD: non-alloc API + cached refs + pooling.
122readonly Collider[] _buf = new Collider[16];
123void Update() {
124 int n = Physics.OverlapSphereNonAlloc(transform.position, 5f, _buf);
125 for (int i = 0; i < n; i++) { /* ... */ }
126}
127```
128
129- **Never** call `Find`/`GetComponent`/`FindObjectsOfType` in `Update` — cache references in `Awake`/`Start`.
130- **Pool** bullets, enemies, VFX with the built-in `ObjectPool<T>` (or your own) instead of `Instantiate`/`Destroy` churn.
131- Prefer **NonAlloc** physics queries and `struct`s/cached buffers in hot paths; boxing and per-frame `new` feed the GC and cause stutter.
132- Avoid `string` concatenation and LINQ in hot loops.
133
134```csharp
135// Object pooling with UnityEngine.Pool.
136using UnityEngine.Pool;
137
138public class BulletPool : MonoBehaviour
139{
140 [SerializeField] private GameObject _bulletPrefab;
141 private ObjectPool<GameObject> _pool;
142
143 void Awake()
144 {
145 _pool = new ObjectPool<GameObject>(
146 createFunc: () => Instantiate(_bulletPrefab, transform),
147 actionOnGet: go => go.SetActive(true),
148 actionOnRelease: go => go.SetActive(false),
149 collectionCheck: true,
150 defaultCapacity: 32,
151 maxSize: 256);
152 }
153
154 public GameObject Spawn(Vector3 pos, Quaternion rot)
155 {
156 var go = _pool.Get();
157 go.transform.SetPositionAndRotation(pos, rot);
158 return go;
159 }
160
161 public void Despawn(GameObject go) => _pool.Release(go);
162}
163```
164
165### 4. Coroutines vs async/await
166
167- **Coroutines** are frame-tied (`yield return null`, `WaitForSeconds`) and auto-stop with the GameObject — good for timed gameplay sequences.
168- **async/await** (with `Awaitable` in Unity 6 or UniTask) suits I/O, Addressables loads, and work that shouldn't be tied to a single object's lifetime — but **you** must cancel it (CancellationToken) when the scene/object goes away, or you touch destroyed objects.
169
170```csharp
171// Coroutine — frame-tied, auto-stops with GameObject.
172IEnumerator ReloadRoutine(float delay)
173{
174 yield return new WaitForSeconds(delay);
175 // resume reload
176}
177
178// async/await with Awaitable (Unity 6) — must cancel on teardown.
179private CancellationTokenSource _cts;
180void OnEnable() => _cts = new CancellationTokenSource();
181void OnDisable() => _cts?.Cancel();
182
183async Awaitable LoadAssetAsync(string key)
184{
185 try
186 {
187 var handle = Addressables.LoadAssetAsync<GameObject>(key);
188 await handle.Task.WaitAsync(_cts.Token);
189 // use handle.Result
190 }
191 catch (OperationCanceledException) { /* expected on teardown */ }
192}
193```
194
195### 5. Addressables
196
197- Move off hard prefab references and `Resources/` (which forces everything into the build and memory). **Addressables** load by address, support remote content, and let you **release** memory explicitly.
198- Track handles and call `Addressables.Release` / release the handle when done — leaked handles keep assets resident.
199- `InstantiateAsync` for spawnables; group and label assets to control what ships and downloads.
200
201```csharp
202// Load, instantiate, and release correctly.
203private GameObject _instance;
204private AsyncOperationHandle<GameObject> _handle;
205
206async Awaitable SpawnEnemyAsync(string address, Vector3 pos)
207{
208 _handle = Addressables.InstantiateAsync(address, pos, Quaternion.identity);
209 await _handle.Task.WaitAsync(_cts.Token);
210 _instance = _handle.Result;
211}
212
213void DespawnEnemy()
214{
215 if (_instance != null)
216 {
217 Addressables.ReleaseInstance(_instance);
218 _instance = null;
219 }
220}
221```
222
223### 6. DOTS / ECS, Jobs, Burst
224
225- Reach for **ECS** when you have thousands of similar entities (bullets, units, boids) where cache-friendly data layout and parallelism dominate. It's a different paradigm (data in components, logic in systems) — don't rewrite a small game in it for novelty.
226- The **C# Job System** + **Burst** compiler parallelize and SIMD-optimize tight numeric work even **without** full ECS — great for procedural gen, pathfinding grids, mesh deformation.
227- Don't touch `UnityEngine` objects (Transforms, GameObjects) from jobs; jobs operate on `NativeArray`/blittable data. Use the Transform access jobs / ECS for transforms.
228
229```csharp
230using Unity.Burst;
231using Unity.Collections;
232using Unity.Jobs;
233using Unity.Mathematics;
234
235[BurstCompile]
236struct VelocityJob : IJobParallelFor
237{
238 public NativeArray<float3> positions;
239 [ReadOnly] public NativeArray<float3> velocities;
240 public float dt;
241
242 public void Execute(int i)
243 {
244 positions[i] += velocities[i] * dt; // blittable data only
245 }
246}
247
248// Schedule from main thread, complete before reading.
249var job = new VelocityJob
250{
251 positions = _positions,
252 velocities = _velocities,
253 dt = Time.deltaTime
254};
255JobHandle handle = job.Schedule(_positions.Length, 64);
256handle.Complete();
257```
258
259### 7. Render pipeline choice
260
261| | URP | HDRP | Built-in (legacy) |
262|---|---|---|---|
263| Target | Mobile, Switch, broad PC, VR | High-end PC/console | Avoid for new projects |
264| Look | Scalable, lighter | Film-grade, physical lights | — |
265| Cost | Lower | Heavy | — |
266
267Pick the pipeline **at project start** — switching later means re-authoring every material. URP is the default for most games; HDRP only when you need its high-end lighting and can afford the hardware target.
268
269## Pitfalls
270
2711. **`GetComponent`/`Find` in `Update`**: cache in `Awake`/`Start`; per-frame lookups are a classic hotspot.
2722. **Physics in `Update`**: rigidbody moves belong in `FixedUpdate`, or motion is framerate-dependent and jittery.
2733. **`Instantiate`/`Destroy` churn**: pool instead; `Destroy` feeds the GC and fragments memory.
2744. **Per-frame allocations**: NonAlloc APIs, no LINQ/string-building in hot loops.
2755. **Everything in `Resources/`**: bloats build + memory; use Addressables and release handles.
2766. **Async work not cancelled**: awaited tasks touching destroyed objects → null refs. Use CancellationToken tied to lifetime.
2777. **Touching Unity objects from jobs**: not thread-safe; jobs use NativeArrays only.
2788. **Switching render pipeline mid-project**: re-authors all materials. Decide URP vs HDRP up front.
2799. **Deep MonoBehaviour inheritance**: prefer composition + ScriptableObject data.
28010. **Coroutines surviving scene loads**: coroutines stop with their GameObject, but a `DontDestroyOnLoad` host keeps them running — verify the host is cleaned up.
28111. **ScriptableObject runtime mutation**: changes to a ScriptableObject at runtime persist in the editor but not in builds. Never rely on runtime mutation for save data.
282
283## Verification
284
285- [ ] Input in `Update`, rigidbody motion in `FixedUpdate`, camera in `LateUpdate`.
286- [ ] No `Find`/`GetComponent`/`FindObjectsOfType` in per-frame code; references cached.
287- [ ] Spawned objects are pooled; hot paths use NonAlloc APIs and avoid LINQ/string alloc.
288- [ ] Shared config lives in ScriptableObjects, not duplicated per instance.
289- [ ] Assets load via Addressables with handles released; not dumped in `Resources/`.
290- [ ] async/await work is cancelled on scene/object teardown.
291- [ ] Jobs/Burst operate on NativeArrays only; no engine-object access inside jobs.
292- [ ] Render pipeline (URP/HDRP) chosen at project start and matches the hardware target.
293
294### Checkable commands
295
296```powershell
297# Confirm Unity project version (Windows / PowerShell).
298Get-Content .\ProjectSettings\ProjectVersion.txt
299
300# List installed packages to verify Input System, Addressables, Burst, Collections, URP/HDRP.
301Get-Content .\Packages\manifest.json | Select-String "inputsystem|addressables|burst|collections|urp|hdrp"
302
303# Check for Resources folder bloat (should be minimal or empty).
304Get-ChildItem -Recurse -Directory -Filter "Resources" | Select-Object FullName
305
306# Search codebase for per-frame anti-patterns (should return zero hits in hot paths).
307Select-String -Path .\Assets\**\*.cs -Pattern "FindObjectsOfType|Find\(|GetComponent" | Where-Object { $_.Line -match "Update|FixedUpdate|LateUpdate" }
308```
309
310## Related skills
311
312- `unity-ai-game-creator` — AI-driven idea→project scaffolding and asset-prompt workflow that sits on top of this engine reference.
313- `game-unreal-engine` — Cross-engine counterpart for C++/Blueprint projects.
314- `game-blender-asset-pipeline` — Authoring/exporting the meshes and rigs Unity imports.
315- `game-fmod-wwise-integration` — Middleware audio that plugs into a Unity build.
316- `game-mobile-store-integration` — IAP, ads, Game Center for Unity mobile builds.
317- `game-steamworks-sdk` — Steam integration for Unity PC builds.
318
319## References
320
321- **Unity 6 Scripting API and Manual** — MonoBehaviour execution order, Input System, Addressables. Load when verifying lifecycle callbacks or Input System action map setup.
322- **Unity DOTS/Entities, C# Job System, and Burst documentation** — Load when implementing ECS systems, scheduling jobs, or writing `[BurstCompile]` code.
323- **Universal RP (URP) and High Definition RP (HDRP) documentation** — Load when configuring render pipeline assets, volume overrides, or shader graph.