@ericrisco/rsc 0.1.35 → 0.1.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/README.md +8 -2
  2. package/manifest.json +241 -2
  3. package/package.json +1 -1
  4. package/scripts/lib/domains.js +1 -0
  5. package/scripts/lib/recommend.js +4 -0
  6. package/skills/game-design/SKILL.md +170 -0
  7. package/skills/game-design/evals/README.md +13 -0
  8. package/skills/game-design/evals/cases.yaml +47 -0
  9. package/skills/game-design/references/mechanics-and-loops.md +78 -0
  10. package/skills/game-design/references/playtesting-and-scope.md +58 -0
  11. package/skills/game-design/references/progression-and-economy.md +70 -0
  12. package/skills/game-storytelling/SKILL.md +159 -0
  13. package/skills/game-storytelling/evals/README.md +28 -0
  14. package/skills/game-storytelling/evals/cases.yaml +51 -0
  15. package/skills/game-storytelling/references/branching-and-state.md +134 -0
  16. package/skills/game-storytelling/references/dialogue-tools.md +117 -0
  17. package/skills/game-storytelling/references/environmental-storytelling.md +71 -0
  18. package/skills/gamedev-multiplayer/SKILL.md +250 -0
  19. package/skills/gamedev-multiplayer/evals/README.md +12 -0
  20. package/skills/gamedev-multiplayer/evals/cases.yaml +44 -0
  21. package/skills/gamedev-multiplayer/references/godot-high-level-multiplayer.md +133 -0
  22. package/skills/gamedev-multiplayer/references/prediction-and-latency.md +104 -0
  23. package/skills/gamedev-multiplayer/references/unity-and-unreal-netcode.md +166 -0
  24. package/skills/gamedev-pathing/SKILL.md +242 -0
  25. package/skills/gamedev-pathing/evals/README.md +14 -0
  26. package/skills/gamedev-pathing/evals/cases.yaml +49 -0
  27. package/skills/gamedev-pathing/references/navmesh-workflow.md +110 -0
  28. package/skills/gamedev-pathing/references/search-algorithms.md +135 -0
  29. package/skills/gamedev-pathing/references/steering-and-avoidance.md +120 -0
  30. package/skills/gamedev-physics/SKILL.md +225 -0
  31. package/skills/gamedev-physics/evals/README.md +12 -0
  32. package/skills/gamedev-physics/evals/cases.yaml +54 -0
  33. package/skills/gamedev-physics/references/character-controllers.md +120 -0
  34. package/skills/gamedev-physics/references/determinism-and-queries.md +124 -0
  35. package/skills/gamedev-physics/references/layers-and-masks.md +115 -0
  36. package/skills/gamedev-shaders/SKILL.md +252 -0
  37. package/skills/gamedev-shaders/evals/README.md +14 -0
  38. package/skills/gamedev-shaders/evals/cases.yaml +45 -0
  39. package/skills/gamedev-shaders/references/effect-recipes.md +205 -0
  40. package/skills/gamedev-shaders/references/godot-shading-language.md +133 -0
  41. package/skills/gamedev-shaders/references/unity-and-unreal-shaders.md +169 -0
  42. package/skills/gamedev-shipping/SKILL.md +236 -0
  43. package/skills/gamedev-shipping/evals/README.md +9 -0
  44. package/skills/gamedev-shipping/evals/cases.yaml +55 -0
  45. package/skills/gamedev-shipping/references/mobile-and-desktop.md +127 -0
  46. package/skills/gamedev-shipping/references/stores-and-ci.md +162 -0
  47. package/skills/gamedev-shipping/references/web-export-headers.md +140 -0
  48. package/skills/godot/SKILL.md +319 -0
  49. package/skills/godot/evals/README.md +13 -0
  50. package/skills/godot/evals/cases.yaml +50 -0
  51. package/skills/godot/references/export-and-testing.md +102 -0
  52. package/skills/godot/references/gdscript-style.md +84 -0
  53. package/skills/godot/references/godot3-to-4-traps.md +89 -0
  54. package/skills/godot/references/nodes-scenes-resources.md +109 -0
  55. package/skills/level-design/SKILL.md +175 -0
  56. package/skills/level-design/evals/README.md +35 -0
  57. package/skills/level-design/evals/cases.yaml +58 -0
  58. package/skills/level-design/references/blockout-to-art.md +118 -0
  59. package/skills/level-design/references/guidance-and-readability.md +152 -0
  60. package/skills/level-design/references/pacing-and-encounters.md +142 -0
  61. package/skills/roast-me/tools/adapters/__pycache__/__init__.cpython-312.pyc +0 -0
  62. package/skills/roast-me/tools/adapters/__pycache__/base.cpython-312.pyc +0 -0
  63. package/skills/roast-me/tools/adapters/__pycache__/claude.cpython-312.pyc +0 -0
  64. package/skills/roast-me/tools/adapters/__pycache__/codex.cpython-312.pyc +0 -0
  65. package/skills/roast-me/tools/adapters/__pycache__/gemini.cpython-312.pyc +0 -0
  66. package/skills/roast-me/tools/adapters/__pycache__/registry.cpython-312.pyc +0 -0
  67. package/skills/unity/SKILL.md +282 -0
  68. package/skills/unity/evals/README.md +8 -0
  69. package/skills/unity/evals/cases.yaml +43 -0
  70. package/skills/unity/references/build-and-platforms.md +65 -0
  71. package/skills/unity/references/input-system.md +102 -0
  72. package/skills/unity/references/lifecycle-deep-dive.md +75 -0
  73. package/skills/unreal/SKILL.md +270 -0
  74. package/skills/unreal/evals/README.md +12 -0
  75. package/skills/unreal/evals/cases.yaml +45 -0
  76. package/skills/unreal/references/blueprint-cpp-parity.md +109 -0
  77. package/skills/unreal/references/gameplay-framework.md +95 -0
  78. package/skills/unreal/references/packaging.md +83 -0
@@ -0,0 +1,282 @@
1
+ ---
2
+ name: unity
3
+ description: "Use when writing, reviewing, or structuring Unity game code in C# for current Unity 6 LTS (6000.x) — GameObjects and Transform hierarchy, MonoBehaviour lifecycle, prefabs and prefab variants, ScriptableObjects for data, scenes and additive loading, the new Input System, coroutines vs async/await/Awaitable, Addressables, and build/player settings for 2D and 3D. Triggers: 'my Unity script', 'Awake vs Start', 'why is my physics jittery', MonoBehaviour .cs files, 'set up the new Input System', 'ScriptableObject config', 'load a scene additively', 'Instantiate a prefab', 'convert Input.GetAxis to the new system', 'build for Android/WebGL', 'por qué no se llama mi Start', 'com carrego una escena en additiu'. NOT Godot/GDScript (that is godot); NOT Unreal/Blueprint/C++ engine work (that is unreal); NOT the netcode wire protocol itself (that is gamedev-multiplayer)."
4
+ tags: [unity, csharp, game-dev, monobehaviour, input-system]
5
+ recommends: [gamedev-multiplayer, gamedev-physics, gamedev-shaders, gamedev-pathing, gamedev-shipping, godot, unreal]
6
+ profiles: [full]
7
+ origin: risco
8
+ ---
9
+
10
+ # Unity + C# (Unity 6 LTS)
11
+
12
+ > Idiomatic C# for the current Unity engine — 2D and 3D. Owns engine-side patterns (components,
13
+ > lifecycle, prefabs, scenes, data, input, async, builds). Not Godot (`godot`) or Unreal (`unreal`);
14
+ > stops at the netcode wire (`gamedev-multiplayer`).
15
+
16
+ ## Version contract — read first
17
+
18
+ **Target: Unity 6 LTS, versioned `6000.x`.** Current LTS at authoring is **Unity 6.3 LTS (`6000.3`)**
19
+ (supported to Dec 2027); **Unity 6.0 LTS (`6000.0`)** to Oct 2026. Unity 6 dropped the year-based names
20
+ (2020/2021/2022 LTS) for the `6000.x` scheme. Confirm the project version in
21
+ `ProjectSettings/ProjectVersion.txt` before assuming an API exists.
22
+
23
+ **Ban-list — never emit these; use the modern replacement:**
24
+
25
+ | Deprecated / removed | Use instead |
26
+ | --- | --- |
27
+ | `Input.GetAxis` / `GetKey` / `GetButton` (legacy Input Manager) | **new Input System** (`com.unity.inputsystem`): `InputActionAsset` / `InputAction` / `PlayerInput` — §6 |
28
+ | `UnityEngine.Networking` (UNet), `NetworkServer`/`NetworkClient`, its `NetworkBehaviour` | **removed** since 2022.2. → **Netcode for GameObjects** (`com.unity.netcode.gameobjects`) + `gamedev-multiplayer` |
29
+ | `Resources.Load(...)` for game content | **Addressables** (`com.unity.addressables`) — §8 |
30
+ | `FindObjectOfType<T>()` / `FindObjectsOfType<T>()` | `FindFirstObjectByType<T>()` / `FindAnyObjectByType<T>()` / `FindObjectsByType<T>(FindObjectsSortMode.None)` (old ones obsolete since 2023.1) |
31
+ | `WWW` | `UnityWebRequest` |
32
+ | `OnGUI` / IMGUI for runtime game UI | **UI Toolkit** (runtime) or uGUI; keep IMGUI for editor tools only |
33
+ | Setting `transform.position` on a `Rigidbody` in `Update` | `Rigidbody.MovePosition/MoveRotation` in `FixedUpdate` — §4 |
34
+ | `GameObject.Find`/`FindWithTag` by string in `Update` | cache the ref in `Awake`, or `[SerializeField]` it |
35
+
36
+ Prefer the new Input System even for single-player prototypes. Keep `Debug.Log` out of hot loops and
37
+ strip it from ships.
38
+
39
+ ## 1. GameObject / Component model & Transform hierarchy
40
+
41
+ A **GameObject** is an empty container; behaviour comes from **Components** you attach
42
+ (`Transform`, `Rigidbody`, `MeshRenderer`, and your `MonoBehaviour` scripts). Every GameObject has
43
+ exactly one `Transform` (or `RectTransform` under a Canvas) giving position/rotation/scale.
44
+
45
+ - Get components: `TryGetComponent(out var rb)` (no-alloc, preferred), `GetComponent<T>()`,
46
+ `GetComponentInChildren/InParent<T>()`. Cache in `Awake` — `GetComponent` in `Update` is a perf sink.
47
+ - Hierarchy: `transform.parent`, `transform.SetParent(newParent, worldPositionStays: true)`,
48
+ `transform.childCount`, `foreach (Transform child in transform)`. Child world = parent × local.
49
+ - Same object model for 2D and 3D: 2D uses `Rigidbody2D`/`Collider2D`/`SpriteRenderer`; 3D uses
50
+ `Rigidbody`/`Collider`/`MeshRenderer`. Never mix 2D and 3D physics components on one body.
51
+
52
+ ```csharp
53
+ [RequireComponent(typeof(Rigidbody))]
54
+ public sealed class Mover : MonoBehaviour
55
+ {
56
+ Rigidbody _rb;
57
+ void Awake() => _rb = GetComponent<Rigidbody>(); // cache once
58
+ }
59
+ ```
60
+
61
+ ## 2. Prefabs & prefab variants; instantiation
62
+
63
+ A **Prefab** is a reusable GameObject template (an asset). A **Prefab Variant** inherits from a base
64
+ prefab and overrides selected properties/children — like subclassing for assets (e.g. `Enemy` base →
65
+ `EnemyFast` variant). Edit the base and variants inherit the change unless they override that value.
66
+
67
+ - Spawn with `Instantiate(prefab, position, rotation, parent)`; it returns the concrete type
68
+ (`var e = Instantiate(_enemyPrefab);` with `[SerializeField] Enemy _enemyPrefab;`). Store the
69
+ serialized reference; do not `Resources.Load` it.
70
+ - Destroy with `Destroy(gameObject)` (end of frame) or `Destroy(obj, delay)`. Never `DestroyImmediate`
71
+ at runtime. For frequently spawned objects (bullets, VFX) **pool** them (`UnityEngine.Pool.ObjectPool<T>`)
72
+ instead of Instantiate/Destroy churn.
73
+ - Editor-only prefab authoring uses `PrefabUtility` (wrap in `#if UNITY_EDITOR`); absent in builds.
74
+
75
+ ## 3. Scenes & scene management (additive loading)
76
+
77
+ A **Scene** holds a set of GameObjects. Register scenes in **Build Profiles → Scene List** (Unity 6;
78
+ formerly Build Settings) so they can load by index or name.
79
+
80
+ ```csharp
81
+ using UnityEngine.SceneManagement;
82
+
83
+ // Additive: keep the current scene, layer another on top (e.g. UI, a level chunk).
84
+ var op = SceneManager.LoadSceneAsync("Level_02", LoadSceneMode.Additive);
85
+ op.completed += _ => Debug.Log("Level_02 loaded");
86
+ await op; // Unity 6: AsyncOperation is awaitable
87
+
88
+ // Unload just that scene later:
89
+ await SceneManager.UnloadSceneAsync("Level_02");
90
+ ```
91
+
92
+ - `LoadSceneMode.Single` (default) unloads everything first; `Additive` composes scenes — the basis of
93
+ streaming worlds, persistent manager scenes, and separate UI scenes.
94
+ - `SceneManager.MoveGameObjectToScene` moves an object between loaded scenes; `DontDestroyOnLoad` objects
95
+ survive `Single` loads (use for a bootstrap/services scene). Prefer `LoadSceneAsync` to avoid a hitch.
96
+
97
+ ## 4. MonoBehaviour lifecycle
98
+
99
+ Order per frame and where each concern belongs (full ordering in `references/lifecycle-deep-dive.md`):
100
+
101
+ | Method | When | Put here |
102
+ | --- | --- | --- |
103
+ | `Awake` | once, on instantiation (even if disabled) | cache `GetComponent`, self-init, no cross-object refs |
104
+ | `OnEnable` | each time the object/component enables | subscribe to events, register callbacks |
105
+ | `Start` | once, before first `Update`, only if active | cross-object wiring (other objects' `Awake` has run) |
106
+ | `FixedUpdate` | fixed timestep (physics tick), 0..n / frame | **all physics** — `Rigidbody` forces/`MovePosition`, `ApplyForce` |
107
+ | `Update` | every frame | input reads, game logic, timers (scale by `Time.deltaTime`) |
108
+ | `LateUpdate` | every frame, after all `Update` | camera follow, look-at, anything tracking moved objects |
109
+ | `OnDisable` | each disable / before destroy | **unsubscribe** everything subscribed in `OnEnable` |
110
+ | `OnDestroy` | once, on destruction | release native/unmanaged resources, final cleanup |
111
+
112
+ Rules that bite:
113
+ - **Physics goes in `FixedUpdate`**, never `Update`. Reading input in `FixedUpdate` drops events —
114
+ read input in `Update`, cache intent, apply forces in `FixedUpdate`.
115
+ - Frame-rate independence: multiply per-frame movement by `Time.deltaTime` (`Update`) — but
116
+ `FixedUpdate` already runs at a fixed `Time.fixedDeltaTime`.
117
+ - `Awake` runs even on inactive objects; `Start` does not run until the object is active. Cross-object
118
+ references belong in `Start`, not `Awake`.
119
+ - Every `OnEnable` subscription needs a matching `OnDisable` unsubscription or you leak and get
120
+ double-fires after re-enable.
121
+
122
+ ## 5. ScriptableObjects for data/config; serialization
123
+
124
+ A **ScriptableObject** is a data asset that lives outside any scene — ideal for config, tuning tables,
125
+ enemy/item definitions, and event channels. One asset is shared by reference (no per-instance copy),
126
+ so it saves memory and lets designers tweak values without touching code.
127
+
128
+ ```csharp
129
+ [CreateAssetMenu(fileName = "WeaponDef", menuName = "Game/Weapon Definition")]
130
+ public sealed class WeaponDefinition : ScriptableObject
131
+ {
132
+ [SerializeField] float _damage = 10f;
133
+ [SerializeField] float _fireRate = 2f;
134
+ public float Damage => _damage; // expose read-only
135
+ public float FireRate => _fireRate;
136
+ }
137
+ ```
138
+
139
+ **`[SerializeField] private` vs `public`:** default to `[SerializeField] private` + a public
140
+ property/method. It shows in the Inspector and survives serialization *without* letting arbitrary code
141
+ mutate the field — encapsulation intact. Use bare `public` only for genuine data bags.
142
+
143
+ **Serialization rules (they trip everyone):**
144
+ - Unity serializes: `public` or `[SerializeField]` fields of supported types (primitives, `string`,
145
+ Unity types, enums, arrays/`List<T>` of those, and `[Serializable]` plain classes/structs).
146
+ - Unity does **not** serialize: properties (use `[field: SerializeField] public float X { get; private set; }`),
147
+ `static`, `readonly`, `const`, `Dictionary<,>` (use two lists or a serializable wrapper), or
148
+ polymorphic references — for interface/abstract fields use `[SerializeReference]`.
149
+ - Do not hold runtime mutable state on a shared ScriptableObject expecting it to reset — it persists in
150
+ the Editor between play sessions. Keep SOs for config; put mutable per-instance state on MonoBehaviours.
151
+
152
+ ## 6. Input System (new) — with a legacy contrast
153
+
154
+ The new Input System (`com.unity.inputsystem`) is enabled by default in Unity 6 and is device-agnostic
155
+ and event-driven. Define an **Input Action Asset** with **Action Maps** (e.g. "Player", "UI") and
156
+ **Actions** (e.g. "Move" = Value/`Vector2`, "Jump" = Button). Generate a C# wrapper or use the
157
+ `PlayerInput` component. Full setup, `PlayerInput`, and rebinding in `references/input-system.md`.
158
+
159
+ ```csharp
160
+ // New Input System — subscribe to the generated actions (no per-frame polling).
161
+ using UnityEngine.InputSystem;
162
+
163
+ public sealed class PlayerController : MonoBehaviour
164
+ {
165
+ InputSystem_Actions _controls; // generated C# class from the .inputactions asset
166
+ Vector2 _move;
167
+
168
+ void Awake() => _controls = new InputSystem_Actions();
169
+ void OnEnable()
170
+ {
171
+ _controls.Player.Enable();
172
+ _controls.Player.Move.performed += ctx => _move = ctx.ReadValue<Vector2>();
173
+ _controls.Player.Move.canceled += _ => _move = Vector2.zero;
174
+ _controls.Player.Jump.performed += _ => Jump();
175
+ }
176
+ void OnDisable() => _controls.Player.Disable();
177
+ }
178
+ ```
179
+
180
+ Legacy contrast (do not write this in new code):
181
+ ```csharp
182
+ // LEGACY Input Manager — string axes, per-frame polling, device-blind. Avoid.
183
+ float x = Input.GetAxis("Horizontal");
184
+ if (Input.GetButtonDown("Jump")) Jump();
185
+ ```
186
+ The new system also polls if you prefer: `_controls.Player.Move.ReadValue<Vector2>()` in `Update`.
187
+
188
+ ## 7. Coroutines vs async/await vs Awaitable
189
+
190
+ | Use | Reach for | Why |
191
+ | --- | --- | --- |
192
+ | Frame-sequenced gameplay (timers, tweens, "wait then spawn") | **Coroutine** or **Awaitable** | frame-aware yields; auto-tie to object lifetime |
193
+ | Unity-native async in Unity 6 (default for new async gameplay) | **`Awaitable`** | main-thread, low-alloc (pooled), frame + thread awaits, cancels via `destroyCancellationToken` |
194
+ | True background CPU work / library `Task` APIs | **`async Task` + `await`** | thread pool; but marshal back — Unity APIs are main-thread only |
195
+
196
+ ```csharp
197
+ // Coroutine — classic, MonoBehaviour-bound, stops when the object disables/destroys.
198
+ IEnumerator SpawnWave()
199
+ {
200
+ yield return new WaitForSeconds(1f);
201
+ Instantiate(_enemyPrefab);
202
+ }
203
+ void Start() => StartCoroutine(SpawnWave());
204
+
205
+ // Awaitable (Unity 6) — the modern replacement. Cancels automatically on destroy.
206
+ async Awaitable SpawnWaveAsync()
207
+ {
208
+ await Awaitable.WaitForSecondsAsync(1f, destroyCancellationToken);
209
+ await Awaitable.NextFrameAsync(destroyCancellationToken);
210
+ Instantiate(_enemyPrefab);
211
+ }
212
+ ```
213
+
214
+ Rules:
215
+ - **Coroutines** run only while the MonoBehaviour is enabled; they die silently on disable. No return
216
+ value; exceptions across `yield` are awkward.
217
+ - **`Awaitable`**: never `await` the same instance twice (pooled → undefined behavior). Pass
218
+ `destroyCancellationToken` so it stops when the object is destroyed. Switch threads with
219
+ `Awaitable.BackgroundThreadAsync()` / `Awaitable.MainThreadAsync()`.
220
+ - **`Task`**: does *not* auto-cancel on destroy — thread a `CancellationToken` yourself, and never touch
221
+ Unity API off the main thread (it throws). Prefer `Awaitable` in Unity 6 unless you need `Task`.
222
+
223
+ ## 8. Addressables (intro) + the Resources anti-pattern
224
+
225
+ **Addressables** (`com.unity.addressables`) is the modern content-loading system: assets get string
226
+ addresses, load asynchronously, and can ship in the build or from a remote CDN with dependency tracking
227
+ and memory-managed release.
228
+
229
+ ```csharp
230
+ using UnityEngine.AddressableAssets;
231
+
232
+ var handle = Addressables.InstantiateAsync("Prefabs/Boss");
233
+ GameObject boss = await handle.Task; // or handle.Completed += ...
234
+ // when done: Addressables.ReleaseInstance(boss); // release to free memory
235
+ ```
236
+
237
+ **`Resources/` is an anti-pattern for game content:** everything under it is forced into the build,
238
+ loaded synchronously, bloats size/startup, and can't be patched or streamed. Reserve it for tiny
239
+ always-needed defaults; migrate real content to Addressables.
240
+
241
+ ## 9. Build settings, platforms & player settings
242
+
243
+ - **Build Profiles** (Unity 6, `File → Build Profiles`) supersede the old Build Settings window: per-platform
244
+ scene list, target platform, and overridable player settings.
245
+ - **Scripting backend:** **IL2CPP** (AOT — required for iOS/consoles/WebGL, faster, harder to reverse)
246
+ vs **Mono** (JIT, Editor/desktop, faster iteration). Set per platform in Player Settings.
247
+ - **Player Settings:** product/company name, bundle identifier, icons, orientation, API compatibility
248
+ level (`.NET Standard 2.1` default), managed stripping. **2D vs 3D** is a template choice, not a
249
+ different build path.
250
+ - WebGL/mobile specifics and the shipping checklist: `references/build-and-platforms.md` + `gamedev-shipping`.
251
+
252
+ ## Guardrails / gotchas
253
+
254
+ - `==`/`!= null` on a destroyed `UnityEngine.Object` works (overloaded), but `?.` and cached refs treat
255
+ a destroyed object as non-null. Re-check with `if (obj)` after possible destruction.
256
+ - Don't mix input systems: with `PlayerInput`, don't also `Input.GetKey` — in "New" mode legacy calls throw.
257
+ - One `Rigidbody` per body (child colliders fine); non-uniform scale breaks physics bodies.
258
+ - Coroutines/`InvokeRepeating` stop on `SetActive(false)`; async `Task`s keep running unless cancelled.
259
+ - No allocation (`new`, LINQ, boxing) in `Update`/`FixedUpdate` hot paths.
260
+
261
+ ## Related skills
262
+
263
+ - `gamedev-multiplayer` — networking/netcode (Netcode for GameObjects); this skill hands off the wire.
264
+ - `gamedev-physics` — deep physics tuning (joints, solver, determinism) beyond "put it in FixedUpdate".
265
+ - `gamedev-shaders` — Shader Graph / HLSL, URP/HDRP materials and rendering.
266
+ - `gamedev-pathing` — NavMesh, agents, steering, path solving.
267
+ - `gamedev-shipping` — store builds, signing, size budgets, platform certification.
268
+ - `godot` / `unreal` — the other engines; route Godot/GDScript and Unreal/Blueprint/C++ there.
269
+
270
+ ## Checklist
271
+
272
+ - [ ] Confirmed the project's Unity version (`ProjectVersion.txt`); no year-based-LTS assumptions.
273
+ - [ ] No banned API emitted (`Input.GetAxis`, `UnityEngine.Networking`, `Resources.Load` for content,
274
+ `FindObjectOfType`, `WWW`, runtime `OnGUI`).
275
+ - [ ] `GetComponent` results cached in `Awake`; no string `Find` in `Update`.
276
+ - [ ] Physics in `FixedUpdate`; input read in `Update`; camera/tracking in `LateUpdate`.
277
+ - [ ] Every `OnEnable` subscription has a matching `OnDisable` unsubscription.
278
+ - [ ] `[SerializeField] private` + property used instead of bare `public` where encapsulation matters.
279
+ - [ ] New Input System used (actions/maps), not legacy polling; systems not mixed.
280
+ - [ ] Async uses `Awaitable` (or coroutine) with `destroyCancellationToken`; no double-await.
281
+ - [ ] Content via Addressables, not `Resources/`.
282
+ - [ ] Scenes registered in Build Profiles; async/additive loading where it avoids a hitch.
@@ -0,0 +1,8 @@
1
+ # unity evals
2
+
3
+ These cases assert the skill fires on Unity/C# engine work (MonoBehaviour lifecycle, prefabs,
4
+ ScriptableObjects, scenes, the new Input System, coroutines/async/Awaitable, Addressables, builds) and
5
+ that it defers correctly: pathfinding→gamedev-pathing, shaders→gamedev-shaders, netcode→gamedev-multiplayer,
6
+ Godot→godot, Unreal→unreal. Capability cases check current Unity 6 patterns (physics in FixedUpdate with
7
+ Rigidbody.MovePosition, new Input System over Input.GetAxis, Awaitable + destroyCancellationToken, no
8
+ double-await) rather than deprecated APIs.
@@ -0,0 +1,43 @@
1
+ skill: unity
2
+ should_trigger:
3
+ - prompt: "My Unity player character teleports and jitters through walls when I move it with the arrow keys. Here's my MonoBehaviour."
4
+ why: "Physics-in-Update / setting transform on a Rigidbody — core lifecycle + FixedUpdate guidance this skill owns."
5
+ - prompt: "What's the difference between Awake and Start in Unity, and where should I grab my other components?"
6
+ why: "Directly the MonoBehaviour lifecycle section (Awake caches, Start does cross-object wiring)."
7
+ - prompt: "Help me convert my old Input.GetAxis(\"Horizontal\") movement to Unity's new Input System with an action map."
8
+ why: "Legacy→new Input System migration; ban-list + §6/input-system reference."
9
+ - prompt: "I want to store all my enemy stats (health, speed, damage) as data assets I can tweak in the Inspector. Best way in Unity?"
10
+ why: "ScriptableObject for data/config + [SerializeField] vs public + serialization rules."
11
+ - prompt: "How do I load a second Unity scene on top of the current one for my UI without unloading the level?"
12
+ why: "Scenes & additive loading (LoadSceneAsync + LoadSceneMode.Additive)."
13
+ - prompt: "Should I use a coroutine, async Task, or Awaitable for a 'wait 2 seconds then spawn' timer in Unity 6?"
14
+ why: "Coroutines vs async/await vs Awaitable decision — §7, including destroyCancellationToken."
15
+ - prompt: "Setting up multiplayer in Unity — I found UNet / UnityEngine.Networking tutorials, do they still work?"
16
+ why: "Version contract: UNet removed → Netcode for GameObjects; routes the wire itself onward but Unity owns the 'it's removed' fact."
17
+ should_not_trigger:
18
+ - prompt: "How do I write a NavMeshAgent that chases the player and avoids obstacles smoothly?"
19
+ route_to: "gamedev-pathing"
20
+ why: "Pathfinding/steering algorithms are the pathing skill; Unity only owns the component wiring."
21
+ - prompt: "Design a Shader Graph for a dissolving-enemy effect with an emissive edge in URP."
22
+ route_to: "gamedev-shaders"
23
+ why: "Shader/material authoring belongs to the shaders skill."
24
+ - prompt: "I'm making a game in Godot 4 with GDScript and my _ready() isn't firing."
25
+ route_to: "godot"
26
+ why: "Godot/GDScript engine — explicitly out of scope; route to godot."
27
+ - prompt: "In Unreal Engine 5 my Blueprint Actor won't replicate movement to clients."
28
+ route_to: "unreal"
29
+ why: "Unreal/Blueprint engine work — route to unreal."
30
+ - prompt: "Write the authoritative server tick and client-side prediction/reconciliation for our netcode."
31
+ route_to: "gamedev-multiplayer"
32
+ why: "Netcode protocol/authority design is the multiplayer skill; Unity stops at 'use Netcode for GameObjects'."
33
+ capability:
34
+ - scenario: "User asks how to move a Rigidbody with input from the new Input System without jitter, in Unity 6."
35
+ must_include:
36
+ - "reads input in Update (caches intent) but applies movement in FixedUpdate"
37
+ - "uses Rigidbody.MovePosition (or AddForce), not setting transform.position on the body"
38
+ - "uses the new Input System (InputAction / action map / ReadValue<Vector2>), not Input.GetAxis"
39
+ - scenario: "User asks whether to use a coroutine or async for a delayed spawn and how to make it stop when the object is destroyed."
40
+ must_include:
41
+ - "recommends Awaitable (or coroutine) over raw Task for Unity gameplay in Unity 6"
42
+ - "passes destroyCancellationToken to the Awaitable so it cancels on destroy"
43
+ - "warns never to await the same Awaitable instance twice (it is pooled)"
@@ -0,0 +1,65 @@
1
+ # Build, platforms & player settings (Unity 6)
2
+
3
+ Reference: Unity Manual "Build Profiles", "Player Settings", "IL2CPP".
4
+
5
+ ## Build Profiles (Unity 6) — replaces the old Build Settings window
6
+
7
+ `File → Build Profiles`. A **Build Profile** is a saved, per-platform configuration:
8
+ - **Scene List** — which scenes are included and their build index (index 0 = first/boot scene). Scenes
9
+ not in the list can only be loaded Additively if already present, so register everything you load.
10
+ - **Target platform & architecture** — Windows/macOS/Linux, Android, iOS, WebGL, consoles.
11
+ - **Overrides** — a profile can override Player Settings (e.g. a "Demo" profile with a different bundle id).
12
+
13
+ `Shared Settings` hold the defaults; each profile diffs from them. Build with `Build` or `Build And Run`.
14
+ Headless/CI builds go through `BuildPipeline.BuildPlayer` in an editor script.
15
+
16
+ ## Scripting backend: IL2CPP vs Mono
17
+
18
+ `Player Settings → Configuration → Scripting Backend`:
19
+
20
+ | | IL2CPP | Mono |
21
+ | --- | --- | --- |
22
+ | How | C# → IL → C++ → native (AOT) | JIT at runtime |
23
+ | Platforms | required for iOS, WebGL, consoles; available desktop/Android | Editor + desktop + Android |
24
+ | Runtime speed | faster | slower |
25
+ | Build time | slower | faster (good for iteration) |
26
+ | Reverse-engineering | harder | easier |
27
+ | Reflection/`dynamic` | AOT limits (no runtime codegen; `System.Reflection.Emit` unsupported) | full |
28
+
29
+ Ship production builds on **IL2CPP**; iterate in the Editor (always Mono/interpreted). IL2CPP + AOT means
30
+ generic code reached only via reflection can be stripped — see managed stripping below.
31
+
32
+ ## Player Settings essentials
33
+
34
+ - **Identity**: Company Name, Product Name, **bundle identifier** (`com.company.game` — must match store
35
+ listing), version + build/bundle number.
36
+ - **Icons & splash**, default orientation (mobile), resolution/presentation.
37
+ - **API Compatibility Level**: `.NET Standard 2.1` (default, smaller) vs `.NET Framework` (broader API,
38
+ larger). Prefer Standard unless a dependency needs Framework.
39
+ - **Managed Stripping Level** (`Minimal`/`Low`/`Medium`/`High`): strips unused IL to shrink builds. High
40
+ can strip types only used via reflection/serialization — preserve them with a `link.xml` or
41
+ `[Preserve]`.
42
+ - **Graphics APIs** per platform (Vulkan/Metal/D3D12/GLES3/WebGPU), color space (Linear recommended).
43
+
44
+ ## Platform quick-notes
45
+
46
+ - **WebGL**: IL2CPP only; **no multithreading by default** (so `System.Threading`/most `Task`
47
+ parallelism is unavailable — `Awaitable` frame awaits are fine); no synchronous file I/O; build size
48
+ and memory matter; use compression (Brotli/Gzip) + a server that serves the right headers.
49
+ - **Android**: set target/min SDK, choose ARM64 (required for Play Store), build **AAB** for the store
50
+ (APK for sideload). Configure keystore signing.
51
+ - **iOS**: Unity emits an Xcode project; sign & archive in Xcode. IL2CPP + ARM64.
52
+ - **Desktop**: simplest; Mono or IL2CPP.
53
+
54
+ ## Rendering pipeline choice (affects builds & shaders)
55
+
56
+ - **URP** (Universal RP) — default for most 2D/3D projects, scales phone→desktop.
57
+ - **HDRP** — high-end desktop/console visuals.
58
+ - **Built-in** — legacy; new projects should pick URP/HDRP.
59
+
60
+ Pipeline choice changes materials and shader authoring — see the `gamedev-shaders` skill.
61
+
62
+ ## Handoff
63
+
64
+ Store submission, signing, size budgets, certification, and release ops belong to the `gamedev-shipping`
65
+ skill. This reference stops at producing a correct platform build from the Editor.
@@ -0,0 +1,102 @@
1
+ # Input System (new) — setup, patterns, migration
2
+
3
+ Package: `com.unity.inputsystem`. Enabled by default in Unity 6. Device-agnostic, event-driven,
4
+ supports rebinding, composites, local multiplayer, and touch. Reference: Unity Input System package
5
+ manual.
6
+
7
+ ## Project mode
8
+
9
+ `Edit → Project Settings → Player → Active Input Handling`:
10
+ - **Input System Package (New)** — legacy `Input.*` calls throw. Recommended for new projects.
11
+ - **Both** — new + legacy coexist (migration only; avoid mixing per-feature).
12
+ - **Input Manager (Old)** — legacy only. Do not target for new work.
13
+
14
+ Unity 6 also has **Project-wide Actions** (`Edit → Project Settings → Input System Package`): a default
15
+ `InputActionAsset` shared across the whole project, reachable via `InputSystem.actions`.
16
+
17
+ ## Anatomy
18
+
19
+ - **Input Action Asset** (`.inputactions`): the container. Enable "Generate C# Class" in its importer to
20
+ get a strongly-typed wrapper (e.g. `InputSystem_Actions`).
21
+ - **Action Map**: a group of actions active together — e.g. "Player", "UI", "Vehicle". Enable/disable
22
+ maps to switch context (`_controls.Player.Disable(); _controls.UI.Enable();`).
23
+ - **Action**: a named input with a **type**:
24
+ - *Value* (continuous, e.g. `Vector2` Move) — `performed` fires on change, `ReadValue<T>()`.
25
+ - *Button* (Jump, Fire) — `started` / `performed` / `canceled` phases.
26
+ - *Pass-Through* (raw device, every event).
27
+ - **Binding**: the physical control → action. **Composite** bindings combine controls, e.g. a "2D Vector"
28
+ composite maps W/A/S/D to a single `Vector2`. **Control schemes** group bindings per device set
29
+ (Keyboard&Mouse, Gamepad).
30
+
31
+ ## Three ways to consume input
32
+
33
+ ### 1. Generated C# class (recommended for a single player)
34
+
35
+ ```csharp
36
+ using UnityEngine.InputSystem;
37
+
38
+ public sealed class PlayerController : MonoBehaviour
39
+ {
40
+ InputSystem_Actions _controls;
41
+ Vector2 _move;
42
+
43
+ void Awake() => _controls = new InputSystem_Actions();
44
+ void OnEnable()
45
+ {
46
+ _controls.Player.Enable();
47
+ _controls.Player.Move.performed += OnMove;
48
+ _controls.Player.Move.canceled += OnMove;
49
+ _controls.Player.Jump.performed += _ => Jump();
50
+ }
51
+ void OnDisable()
52
+ {
53
+ _controls.Player.Move.performed -= OnMove;
54
+ _controls.Player.Move.canceled -= OnMove;
55
+ _controls.Player.Disable();
56
+ }
57
+ void OnDestroy() => _controls.Dispose(); // it owns native resources
58
+ void OnMove(InputAction.CallbackContext ctx) => _move = ctx.ReadValue<Vector2>();
59
+ }
60
+ ```
61
+
62
+ ### 2. Polling (when event-driven feels heavy)
63
+
64
+ ```csharp
65
+ Vector2 move = _controls.Player.Move.ReadValue<Vector2>();
66
+ bool jumped = _controls.Player.Jump.WasPressedThisFrame(); // edge-triggered, read in Update
67
+ ```
68
+
69
+ ### 3. `PlayerInput` component (fastest wiring, local multiplayer)
70
+
71
+ Attach `PlayerInput`, assign the action asset, pick a **Behavior**:
72
+ - *Send Messages* / *Broadcast Messages* — calls `OnMove(InputValue)` etc. by name.
73
+ - *Invoke Unity Events* — wire in the Inspector.
74
+ - *Invoke C# Events* — subscribe in code.
75
+
76
+ For local co-op, `PlayerInputManager` spawns a `PlayerInput` per joined device, isolating each player's
77
+ action instance and pairing devices automatically.
78
+
79
+ ## Rebinding at runtime
80
+
81
+ ```csharp
82
+ var rebind = _controls.Player.Jump.PerformInteractiveRebinding()
83
+ .WithControlsExcluding("Mouse")
84
+ .OnComplete(op => { op.Dispose(); SaveBindings(); })
85
+ .Start();
86
+ // Persist: string json = _controls.asset.SaveBindingOverridesAsJson();
87
+ // Restore: _controls.asset.LoadBindingOverridesFromJson(json);
88
+ ```
89
+
90
+ ## Migration from legacy
91
+
92
+ | Legacy | New Input System |
93
+ | --- | --- |
94
+ | `Input.GetAxis("Horizontal")` | Move action (Value/`Vector2`) → `ReadValue<Vector2>().x` |
95
+ | `Input.GetButtonDown("Jump")` | Jump action (Button) → `WasPressedThisFrame()` or `performed` |
96
+ | `Input.GetKey(KeyCode.E)` | action bound to `<Keyboard>/e` → `IsPressed()` |
97
+ | `Input.mousePosition` | `Mouse.current.position.ReadValue()` |
98
+ | `Input.GetMouseButtonDown(0)` | `Mouse.current.leftButton.wasPressedThisFrame` |
99
+ | `Input.touchCount` / `Input.GetTouch` | `Touchscreen.current` / Enhanced Touch API |
100
+
101
+ Do not leave `Input.*` polling alongside new-system actions — in "New" mode the legacy calls throw, and
102
+ in "Both" mode you double-handle the same physical input.
@@ -0,0 +1,75 @@
1
+ # MonoBehaviour lifecycle — deep dive (Unity 6)
2
+
3
+ Full execution order for a `MonoBehaviour`, and the exact reason each callback exists. Reference:
4
+ Unity Manual "Order of execution for event functions".
5
+
6
+ ## Initialization (once per object, in this order)
7
+
8
+ 1. **`Awake`** — called when the script instance is loaded, **even if the component is disabled**, and
9
+ before any `Start`. Cache `GetComponent`/`TryGetComponent`, allocate internal state. Do NOT reach
10
+ into *other* objects here — their `Awake` may not have run yet.
11
+ 2. **`OnEnable`** — every time the object/component becomes enabled (including re-enable). Subscribe to
12
+ C# events, register with managers, enable input actions. Must be mirrored by `OnDisable`.
13
+ 3. **`Start`** — once, just before the first `Update`, and **only if the component is active**. Safe
14
+ place for cross-object wiring because every object's `Awake` has already run. If an object is created
15
+ disabled and never enabled, `Start` never runs.
16
+
17
+ Across a scene: all `Awake`s run, then all `OnEnable`s, then all `Start`s — so `Start` is your
18
+ "everyone exists now" hook.
19
+
20
+ ## Physics loop (`FixedUpdate`) — 0..n times per frame
21
+
22
+ - Runs on a fixed timestep (`Time.fixedDeltaTime`, default 0.02s = 50 Hz). May run zero times (high FPS)
23
+ or several times (low FPS) per rendered frame.
24
+ - **All `Rigidbody` work goes here:** `AddForce`, `MovePosition`, `MoveRotation`, velocity changes.
25
+ Setting `transform.position` directly on a physics body fights the solver → jitter/tunneling.
26
+ - Do NOT read edge-triggered input here (`WasPressedThisFrame`) — you'll miss events. Read in `Update`,
27
+ store the intent, consume it in `FixedUpdate`.
28
+ - Collision/trigger callbacks (`OnCollisionEnter`, `OnTriggerEnter`, and their `Stay`/`Exit`, plus 2D
29
+ variants) fire from the physics step.
30
+
31
+ ## Game logic loop (per frame)
32
+
33
+ 4. **`Update`** — once per rendered frame. Input, timers, non-physics movement, state machines.
34
+ Frame-rate independent movement multiplies by `Time.deltaTime`.
35
+ 5. **`LateUpdate`** — after every `Update` in the scene has run. Camera follow, look-at, IK, procedural
36
+ bone adjustments — anything that must read the *final* positions of objects that moved this frame.
37
+
38
+ ## Rendering-adjacent (advanced)
39
+
40
+ - `OnPreCull`, `OnBecameVisible`/`OnBecameInvisible`, `OnWillRenderObject`, `OnRenderImage` (Built-in RP;
41
+ URP/HDRP use `RenderPipelineManager` callbacks / render features instead).
42
+ - `OnDrawGizmos` / `OnDrawGizmosSelected` — Editor scene-view debug drawing only.
43
+ - `OnGUI` — legacy IMGUI, called multiple times per frame; editor tooling only, never runtime gameplay.
44
+
45
+ ## Teardown
46
+
47
+ 6. **`OnDisable`** — when the object/component disables (and just before `OnDestroy`). Unsubscribe from
48
+ everything subscribed in `OnEnable`, disable input actions, stop coroutines you own. A missing
49
+ unsubscribe here is the #1 cause of leaks and "handler fired twice after re-enable".
50
+ 7. **`OnDestroy`** — once, when the object is destroyed (or scene unloads / app quits). Release native
51
+ handles, dispose `IDisposable`s (`NativeArray`, `InputActionAsset` you `new`ed), final cleanup.
52
+ 8. **`OnApplicationQuit`** / `OnApplicationPause` / `OnApplicationFocus` — app-level lifecycle for
53
+ save-on-quit and mobile pause handling.
54
+
55
+ ## Coroutine yield timing (where a coroutine resumes)
56
+
57
+ | `yield return` | Resumes |
58
+ | --- | --- |
59
+ | `null` | next frame, after `Update` |
60
+ | `new WaitForSeconds(t)` | after `t` scaled seconds (affected by `Time.timeScale`) |
61
+ | `new WaitForSecondsRealtime(t)` | after `t` real seconds (ignores `timeScale`) |
62
+ | `new WaitForFixedUpdate()` | after the next physics step |
63
+ | `new WaitForEndOfFrame()` | after rendering, before present (good for screen capture) |
64
+ | `new WaitUntil(() => cond)` / `WaitWhile(...)` | when the predicate flips |
65
+ | another `IEnumerator` | when the nested coroutine completes |
66
+
67
+ Gotcha: `new WaitForSeconds(t)` allocates every call — cache the instance if you yield it in a loop, or
68
+ switch to `Awaitable.WaitForSecondsAsync`.
69
+
70
+ ## Script execution order
71
+
72
+ If object A must initialize before object B, don't rely on scene order — set it in
73
+ `Project Settings → Script Execution Order`, or better, express the dependency explicitly (have B pull
74
+ what it needs in its own `Start`, or use an explicit init call). `[DefaultExecutionOrder(n)]` sets it
75
+ per-class in code.