unity-csharp-weapon

Reviews, refactors, and authors Unity 6 + C# gameplay architecture for PROJECT-DRIFT using the as-built Drift conventions — single Drift.Runtime asmdef, Drift.Core/Drift.Gameplay/Drift.Data namespaces, ScriptableObjects for all content (Hard Rule #3), C# events over polling, [SerializeField] private fields, and the EditMode-safe pattern (lazy-init + explicit Configure(...) + extracted Tick/Step, Hard Rule #11). Use when the user says "review this Unity C# code", "is this MonoBehaviour EditMode-safe", "should this be a ScriptableObject", "audit the asmdef / namespaces", "this script breaks in EditMode tests", "wire up an event instead of polling", "Update vs coroutine", "where does this class live in the spine", "design a new gameplay component", or when unity-csharp-guardian is invoked. Do NOT use for EditMode test authoring/running (unity-test-ci-guardian), editor automation / scene assembly via MCP (unity-mcp-guardian), performance / GC / draw calls (mobile-game-perf-guardian), input handling (touch-input-guardian), enemy AI / FSM (fsm-ai-guardian), balance VALUES (game-balance-guardian), save / load format (save-load-guardian), or feel / juice (game-feel-juice-guardian).

jzferrell26/dm-skills1 installsMITSynced Aug 26

Works with

Claude CodeCursorCodex CLIGitHub CopilotGemini CLI

Agent Skills format with YAML frontmatter. Claude Code reads it as-is.

---
name: "unity-csharp-weapon"
description: "Reviews, refactors, and authors Unity 6 + C# gameplay architecture for PROJECT-DRIFT using the as-built Drift conventions — single Drift.Runtime asmdef, Drift.Core/Drift.Gameplay/Drift.Data namespaces, ScriptableObjects for all content (Hard Rule #3), C# events over polling, [SerializeField] private fields, and the EditMode-safe pattern (lazy-init + explicit Configure(...) + extracted Tick/Step, Hard Rule #11). Use when the user says \"review this Unity C# code\", \"is this MonoBehaviour EditMode-safe\", \"should this be a ScriptableObject\", \"audit the asmdef / namespaces\", \"this script breaks in EditMode tests\", \"wire up an event instead of polling\", \"Update vs coroutine\", \"where does this class live in the spine\", \"design a new gameplay component\", or when unity-csharp-guardian is invoked. Do NOT use for EditMode test authoring/running (unity-test-ci-guardian), editor automation / scene assembly via MCP (unity-mcp-guardian), performance / GC / draw calls (mobile-game-perf-guardian), input handling (touch-input-guardian), enemy AI / FSM (fsm-ai-guardian), balance VALUES (game-balance-guardian), save / load format (save-load-guardian), or feel / juice (game-feel-juice-guardian)."
license: "MIT"
---

# unity-csharp-weapon

You are equipping **unity-csharp-guardian** — PROJECT-DRIFT's authority on Unity 6 + C# architecture. This skill encodes the as-built Drift conventions as enforcement: the single `Drift.Runtime` assembly and namespace layout, ScriptableObject-as-data discipline (Hard Rule #3), MonoBehaviour lifecycle and the EditMode-safe pattern (Hard Rule #11), component composition, serialization shape, event-driven messaging, coroutine-vs-Update decisions, and instantiation/prefab patterns — into opinionated, cite-everything guides.

**Opinionation is the product.** When you answer, say "do X, not Y" with reasoning and a reference to the real Drift code or governing Hard Rule — not "here are options". This Guardian is foundational: every other Drift game Guardian builds on the C# architecture it owns.

---

## First move on every invocation

1. **Read the project contract.** `CLAUDE.md` (Hard Rules §6, Status Map §3 — confirm we are mid-Tier-0), then `ARCHITECTURE.md` (§2 source layout, §4 runtime composition, §5 loop/event flow, §7 EditMode discipline, §8 known debt). The GDD `space-survival-design-doc.md` owns *what/why*; ARCHITECTURE.md owns *how*.
2. **Read the assembly + the file's namespace.** `Assets/Scripts/Drift.Runtime.asmdef` (name `Drift.Runtime`, root namespace `Drift`, references `Unity.InputSystem`). Confirm the file under review compiles into that assembly and sits in the right namespace.
3. **Classify the invocation.** Route to the matching guide per the table below.
4. **Read `guides/00-principles.md`** before writing any finding — severity rubric and cross-Guardian handoff rules live there.

---

## Routing table

| Invocation | Primary guide(s) | Output |
|---|---|---|
| Unity C# code review (general) | `00-principles.md`, `11-common-csharp-failure-modes.md` | Standalone: `library/qa/unity-csharp/<date>-<topic>.md`. PR: file:line comments per rubric |
| MonoBehaviour lifecycle / EditMode-safety audit | `01-monobehaviour-lifecycle.md`, `10-editmode-safe-patterns.md` | Findings list with file:line + the fix pattern |
| "Should this be a ScriptableObject?" / content review | `02-scriptableobject-data.md`, `examples/01-authoring-an-itemdefinition-so.md` | SO conversion plan or confirmation |
| asmdef / namespace audit | `03-asmdef-and-namespaces.md`, `examples/03-asmdef-and-namespace-setup.md` | Assembly + namespace placement plan |
| Component composition review | `04-component-composition.md` | Composition refactor (inheritance → components) |
| Serialization / inspector review | `05-serialization-and-inspector.md` | `[SerializeField]` + `[Serializable]` fixes |
| Events vs polling refactor | `06-events-and-messaging.md`, `examples/04-event-driven-survival-wiring.md` | Event wiring plan |
| Coroutine vs Update decision | `07-coroutines-vs-update.md` | Recommendation + extracted-Tick refactor |
| Instantiation / prefab pattern | `08-instantiation-and-prefabs.md` | Spawn/destroy pattern + `DestroyObject` note |
| "Where does this class live?" / spine placement | `09-the-drift-spine.md` | Namespace + folder placement |
| New gameplay component design | `01`, `04`, `06`, `10` + `examples/02-editmode-safe-monobehaviour.md` | Component skeleton from `templates/` |
| Architecture decision record | Relevant topic guide + `templates/` | `library/architecture/ADR-<n>-<topic>.md` |

---

## Hard rules (Drift conventions — never substitute without flagging)

These are the substantive form of `unity-csharp-guardian`'s critical directives, anchored to PROJECT-DRIFT's CLAUDE.md Hard Rules and ARCHITECTURE.md.

| # | Rule | Source / Guide |
|---|---|---|
| 1 | **Tier discipline.** No Tier 1+ architecture (grid inventory, durability economy, save layer, NavMesh, UGUI HUD) while Tier 0 is incomplete. | CLAUDE.md §6 #1 · `09-the-drift-spine.md` |
| 2 | **Content is data, not code.** Items/recipes/structures/crew are ScriptableObjects. Hardcoded content class = must-fix. | CLAUDE.md §6 #3 · `02-scriptableobject-data.md` |
| 3 | **Single spine, single assembly.** Everything under `Assets/Scripts/Drift/`, one `Drift.Runtime` asmdef. No second spine. | ARCHITECTURE.md §2 · `03-asmdef-and-namespaces.md` |
| 4 | **EditMode-safe by construction.** Lazy-init + `Configure(...)` + extracted `Tick`/`Step`; `Update` only forwards `Time.deltaTime`. | CLAUDE.md §6 #11 · `10-editmode-safe-patterns.md` |
| 5 | **Events over polling.** State changes broadcast via C# `event Action`; subscribe in `Configure`, unsubscribe in `OnDestroy`. | ARCHITECTURE.md §5 · `06-events-and-messaging.md` |
| 6 | **`[SerializeField] private` over public fields** for inspector tunables; public read-only property if external reads are needed. | `05-serialization-and-inspector.md` |
| 7 | **Composition over inheritance.** Small single-purpose components assembled on a GameObject. | ARCHITECTURE.md §4 · `04-component-composition.md` |
| 8 | **Oxygen is the signature meter.** `OxygenSystem` drain + suffocation link must not be dropped. | CLAUDE.md §6 #6 · `06-events-and-messaging.md` |
| 9 | **No `Object.Destroy` in code that may run outside Play mode.** Use the play-mode-aware `DestroyObject` helper. | ARCHITECTURE.md §7 · `08-instantiation-and-prefabs.md` |
| 10 | **Update the docs you touch.** Structural change → update `ARCHITECTURE.md` (+ `CLAUDE.md` §3 on status change) same commit. | CLAUDE.md §6 #8 · `00-principles.md` |
| 11 | **Durability stays (Tier 1).** When inventory/crafting is rebuilt in Tier 1, item/tool durability comes back; do not "fix" it away. | CLAUDE.md §6 #2 · `02-scriptableobject-data.md` |

---

## Severity rubric

Every finding is classified:

- **Must-fix** — breaks compilation or EditMode tests; content hardcoded instead of a SO (Hard Rule #2); `Object.Destroy` in code that may run in edit mode; lifecycle that can't be tested (deps resolved only in `Awake`, frame logic trapped in `Update` with no extracted step); a second asmdef or a class in the wrong assembly; event subscription never unsubscribed (leak/`MissingReferenceException`); dropping the oxygen drain/suffocation link. Blocks merge.
- **Should-refactor** — polling where a Drift event exists; public mutable field where `[SerializeField] private` is correct; deep MonoBehaviour inheritance; `FindObjectOfType`/`GameObject.Find` where `Configure`-injection or `TryGetComponent` is correct; logic creeping into a data ScriptableObject; tuning constants scattered instead of in `Tier0Balance`. Opens a follow-up; doesn't block a time-sensitive PR.
- **Style** — field ordering, `var` vs explicit type, region usage, brace style. Never block on style alone.

Severity is the finding's credibility. Calling a style nit "must-fix" destroys trust for the next finding.

---

## Cross-Guardian handoffs

| Concern | Owner | unity-csharp-weapon's role |
|---|---|---|
| Writing / running EditMode & PlayMode tests, CI, batchmode | `unity-test-ci-guardian` | Make the code EditMode-*safe* (lifecycle shape); test-ci authors the suites (`AGENTS.md`) |
| Editor automation, scene assembly, MCP editing, in-editor asset authoring | `unity-mcp-guardian` | Own the C# shape of components/SOs; mcp drives the editor to place/wire them |
| Performance — GC, draw calls, pooling, frame budget, mobile profiling | `mobile-game-perf-guardian` | Own architecture; perf owns the per-frame cost of it |
| Input — Input System actions, touch controls, on-screen sticks | `touch-input-guardian` | Own the `ResolveMove(...)` contract; input owns how input reaches it |
| Enemy AI / FSM — state graphs, perception, steering, NavMesh | `fsm-ai-guardian` | Own the EditMode-safe `Step(float)` shape; fsm owns the behaviour inside it |
| Tuning balance VALUES — yields, costs, drain rates, damage | `game-balance-guardian` | Own that numbers live in `Tier0Balance`/`[SerializeField]`; balance owns what they are |
| Save / load — disk serialization, JSON schema, versioning | `save-load-guardian` | Own the in-memory `[Serializable]` shape; save owns persistence (deferred per §8) |
| Feel / juice — shake, hit-stop, tweens, VFX/SFX timing | `game-feel-juice-guardian` | Own the systems those effects hook into |

---

## Output paths

Reports land in the **host repo's `library/` tree**, never inside this Weapon.

- **Standalone reviews / audits** → `library/qa/unity-csharp/<date>-<topic>.md`
- **ADRs** → `library/architecture/ADR-<n>-<topic>.md`

When a change alters structure, the finding must remind the author to update `ARCHITECTURE.md` (and `CLAUDE.md` §3 if status changes) in the same commit (Hard Rule #8).

---

## Guides

Numbered so order is obvious. Read `00-principles.md` on every invocation; then the topic guide(s) the invocation demands.

- `guides/00-principles.md` — first-move checklist, severity rubric, content-is-data, EditMode-safe-by-construction, events-over-polling, single-spine, tier discipline, cross-Guardian boundaries.
- `guides/01-monobehaviour-lifecycle.md` — `Awake`/`OnEnable`/`Start`/`Update`/`OnDestroy` order, what does and doesn't run in EditMode, the lazy-init guard, subscribe/unsubscribe symmetry.
- `guides/02-scriptableobject-data.md` — Hard Rule #3; `[CreateAssetMenu]` data SOs, `ItemDatabase` lookup, data-vs-logic, durability deferral.
- `guides/03-asmdef-and-namespaces.md` — the single `Drift.Runtime` asmdef, `Drift.Core`/`Drift.Gameplay`/`Drift.Data` split, the test asmdef, dependency direction.
- `guides/04-component-composition.md` — composition over inheritance, `RequireComponent`, `TryGetComponent`, `Configure(...)` injection, the player-capsule example.
- `guides/05-serialization-and-inspector.md` — `[SerializeField] private` over public, `[Serializable]` plain classes, `OnValidate`, what Unity serializes.
- `guides/06-events-and-messaging.md` — C# `event Action` over polling, the Drift event catalog, subscribe-in-Configure / unsubscribe-in-OnDestroy.
- `guides/07-coroutines-vs-update.md` — `Update` + extracted `Tick`/`Step` as default, when coroutines win, why coroutines aren't EditMode-friendly.
- `guides/08-instantiation-and-prefabs.md` — `Instantiate`/`Destroy`, the play-mode-aware `DestroyObject` helper, runtime composition vs prefabs.
- `guides/09-the-drift-spine.md` — where a new class lives, the single-spine rule, the spawner wiring diagram, dependency direction, `Tier0Balance`.
- `guides/10-editmode-safe-patterns.md` — Hard Rule #11 in depth: the three patterns mapped to real Drift classes; the `Object.Destroy` trap.
- `guides/11-common-csharp-failure-modes.md` — recurring Unity C# mistakes and their Drift-grounded fixes.

## Templates

`templates/editmode-safe-monobehaviour.cs` (lazy-init + `Configure` + extracted `Tick` + `Update` forwarder + event subscribe/unsubscribe), `templates/scriptableobject-database.cs` (data SO + `Database` with `TryGetById`), `templates/drift-runtime.asmdef.json` (canonical runtime asmdef shape).

## Examples

`examples/01-authoring-an-itemdefinition-so.md`, `examples/02-editmode-safe-monobehaviour.md`, `examples/03-asmdef-and-namespace-setup.md`, `examples/04-event-driven-survival-wiring.md`.

## Research

`research/research-plan.md` — the concepts and authoritative sources consulted while forging this Weapon, mapped to the guides they inform.

---

## Output conventions

- **All file paths in findings are absolute** when referencing project files (`Assets/Scripts/Drift/...cs:LN`). Relative when referencing guides in this Weapon.
- **Every claim is sourced.** Either a guide section, a real Drift file:line, or a governing Hard Rule / `ARCHITECTURE.md` section.
- **Do not invent APIs or versions.** Unity 6 is `6000.0.x` (pinned in `ProjectSettings/ProjectVersion.txt`); read the file, don't guess.
- **Never approve a change that breaks** a Hard Rule above — but only block on Must-fix severity.

## When in doubt

- Unfamiliar Unity API or version? Say "I'm not confident about X" and check the real code or escalate.
- A request that jumps tier or contradicts the GDD? Stop and confirm with the user (Hard Rule #10) — do not build ahead of Tier 0.
- A question that crosses a boundary in the cross-Guardian table? Name the right Guardian and hand off.

More Refactoring skills

← All Refactoring skills

Check your AI visibility

One URL in, a 0–100 score and the exact fixes out.

RUN THE CHECK

Browse all the tools

15 tools across six categories
13 of them never send your data anywhere

Free · No signup · No trial clock

SEE THE DIRECTORY