One-time stack setup per Docs/dots-setup-task.md (Unity 6.4.7 / 6000.4.7f1).
Packages: entities 6.4.0, entities.graphics 6.4.0, netcode 1.13.2, physics 1.4.6.
- Assets/_Project asmdef split: ProjectM.Simulation/Client/Server/Authoring (root ns ProjectM)
- GameBootstrap : ClientServerBootstrap; verified separate client + server worlds in Play Mode
- Gameplay subscene wired into SampleScene as a baking target
- Heartbeat component + Burst ISystem; EditMode smoke test green (1/1)
- In-repo Obsidian vault (Docs/Vault) incl. DR-001 (plain-Entities test over internal NetCodeTestWorld)
- Portable .mcp.json (basic-memory + serena via ${CLAUDE_PROJECT_DIR}); CLAUDE.md conventions
- .gitignore for DOTS baking cache + machine-local config
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
9.1 KiB
One-Time Project Setup Task — DOTS + Netcode + Memory Stack
This is the separate setup task referenced by the /dots-dev skill. Run it ONCE per project (some steps once per machine — see §0). It installs the DOTS stack, scaffolds the project + vault, wires the memory MCPs, and writes CLAUDE.md. After this completes, /dots-dev drives feature work; this file is no longer needed (keep it for reference / the second machine).
How to run: open a normal Claude Code session in this project (NOT a worktree — the open Unity Editor + UnityMCP target the live working copy) and say "Run the DOTS setup task in Docs/dots-setup-task.md." Work top to bottom; each step has a verification.
Conventions reference: the ECS rules and context7 library IDs live in the skill at
~/.claude/skills/dots-dev/references/dots-conventions.mdand…/context7-libraries.md(Windows:%USERPROFILE%\.claude\skills\dots-dev\references\). Use context7 for any current API shape — do not trust memory for DOTS APIs.
Cross-platform rule: never write a machine-specific absolute path (
/Users/...,C:\...) into any committed file. Use${CLAUDE_PROJECT_DIR}and repo-relative paths. The vault lives in-repo so it travels via git.
§0 — Per-machine prerequisites (do on EACH machine, once)
- Install uv / uvx (for the
basic-memoryandserenaMCP servers). macOS:brew install uvor the official installer; Windows: the official installer /winget install astral-sh.uv. - Install the Obsidian app and the obsidian-cli (the
obsidian-cliskill drives it). Point Obsidian at<repo>/Docs/Vaultonce it exists (§5). - Copy/sync the
dots-devskill to this machine's user skills dir (~/.claude/skills/dots-dev/on macOS,%USERPROFILE%\.claude\skills\dots-dev\on Windows). It is path-agnostic — same files on both. - Confirm Unity 6.4 opens the project and the CoplayDev Unity-MCP bridge connects (
mcpforunity://editor/state→ready_for_tools).
The repo-committed parts (§1–§6) are done once total; §0 is the only per-machine work.
§1 — Install the DOTS stack
Add these to Packages/manifest.json (it is NOT a .csproj/.sln — editing it is correct) or via UnityMCP manage_packages(action="add", ...). Let UPM resolve the version compatible with Unity 6.4; then pin from Packages/packages-lock.json.
com.unity.entitiescom.unity.netcode← Netcode for Entities (ECS). NOTcom.unity.netcode.gameobjects.com.unity.physics← Unity Physics (DOTS), if the game needs collision/triggerscom.unity.entities.graphics← renders entities under URP (already on URP 17.4)
(com.unity.burst, com.unity.collections, com.unity.mathematics, com.unity.transport come transitively.)
read_consoleuntil clean after the domain reload. Verify:manage_packages(action="list")shows all four;packages-lock.jsonrecords the resolved versions.- Optional cleanup: the template's
com.unity.visualscriptingandTutorialInfo/Readme.assetare unused for a DOTS game — remove if you don't want them (delete the asset and its.metatogether).
§2 — Project structure & asmdefs
Pick a root namespace (e.g. ProjectM) and record it in CLAUDE.md. Create a Netcode-aware assembly split under Assets/_Project/:
Assets/_Project/
Scripts/
Simulation/ <Root>.Simulation.asmdef → Entities, Collections, Mathematics, Burst, Unity.Physics, Unity.NetCode
Client/ <Root>.Client.asmdef → Simulation, Entities, Unity.NetCode, Unity.Entities.Graphics
Server/ <Root>.Server.asmdef → Simulation, Entities, Unity.NetCode
Authoring/ <Root>.Authoring.asmdef → Simulation, Entities, Unity.NetCode
Subscenes/
Prefabs/
- Shared Simulation = components + systems that run in BOTH client and server worlds. Client/Server hold world-specific systems; Authoring holds
…AuthoringMonoBehaviours +Baker<T>. - Verify against the official ECS Samples / Netcode sample layout (context7 ID
/unity-technologies/entitycomponentsystemsamples) — adjust the split if the current sample differs. Confirm each asmdef compiles (read_console). - Never create/edit
.csproj/.sln; only.asmdef.
§3 — Bootstrap & worlds
- Add a
ClientServerBootstrapsubclass (confirm exact method names —CreateClientWorld/CreateServerWorld/WorldSystemFilter— via context7…com_unity_netcode_…). - Create a minimal subscene so baking has a target.
- Verify: entering Play Mode creates separate client and server
Worlds (check the Entities Hierarchy / world dropdown).
§4 — Smoke test (prove it compiles AND ticks)
- One trivial unmanaged component (
struct Heartbeat : IComponentData { public int Tick; }) + oneISystem+[BurstCompile]that increments it inSimulationSystemGroup. - One
NetCodeTestWorldEditMode test that boots in-process client+server, connects, ticks N times, and asserts the component advanced. (Get the currentNetCodeTestWorldAPI from context7.) - Verify:
run_tests(mode="EditMode")→ green; console clean of Burst/source-gen errors.
§5 — In-repo vault
Create <repo>/Docs/Vault/ via the obsidian-cli skill (plain markdown is fine if obsidian-cli isn't set up yet):
Docs/Vault/
00_Home/Home.md (Map of Content)
01_Vision/ (pillars, locked decisions)
02_Game_Design/ (systems design docs)
06_Roadmap/{Milestones,Backlog}.md
07_Sessions/<year>/ (session logs)
07_Sessions/_Decisions/ (decision records, DR-001…)
_Templates/{Session_Log,Decision_Record}_Template.md
_Meta/{Documentation_Protocol,Tags}.md
- Point the Obsidian app at this folder as a vault.
- Verify: obsidian-cli can list/read a note here.
§6 — Memory MCPs (.mcp.json, committed, portable)
Create <repo>/.mcp.json (or merge into existing) using ${CLAUDE_PROJECT_DIR} so it loads unchanged on both machines:
{
"mcpServers": {
"basic-memory": {
"command": "uvx",
"args": ["basic-memory", "mcp"]
},
"serena": {
"command": "uvx",
"args": ["--from", "git+https://github.com/oraios/serena",
"serena", "start-mcp-server",
"--context", "ide-assistant",
"--project", "${CLAUDE_PROJECT_DIR}"]
}
}
}
- Configure basic-memory's project to point at the vault:
basic-memory project add gamevault "<repo>/Docs/Vault"(and set it default), per basic-memory's current docs. Verify: a semantic recall returns a hit on a vault note. - Run serena onboarding; test
find_symbolon the §4 smoke-test system.- ⚠️ Serena C# caveat: its language server is flaky on Unity (auto-installs the wrong .NET,
.slnload timeouts). Iffind_symbolerrors/stalls, record it inCLAUDE.mdand fall back toGlob/Grep— or addclaude-context(local LanceDB vector index overAssets/+ the vault) as the documented code-search fallback. Prefer local embeddings (FastEmbed/Ollama) to keep game code off third-party APIs.
- ⚠️ Serena C# caveat: its language server is flaky on Unity (auto-installs the wrong .NET,
- Verify:
.mcp.jsoncontains no machine-specific absolute paths (only${CLAUDE_PROJECT_DIR}), so it loads on the other machine as-is.
§7 — CLAUDE.md (repo root, committed)
Write <repo>/CLAUDE.md covering:
- Project root namespace + the asmdef split from §2.
- The DOTS/ECS conventions (summarize / link the skill's
dots-conventions.md):ISystem+Burst default, unmanagedIComponentData,IEnableableComponent, baking, jobs+allocators, ECB for structural changes, determinism (no wall-clock in predicted sim), server-authoritative + input-only clients,[GhostField]/ghost authoring. Aspects deprecated (1.4). - Guardrails (still valid from classic Unity): never edit
.metaindependently of its asset; never read/writeLibrary/,Temp/,obj/,Logs/,UserSettings/; never edit/commit.csproj/.sln; no edits during Play Mode. - "Which memory tool when": serena = C# symbols, basic-memory = design knowledge over the vault, grep = literals, context7 = current DOTS APIs, native memory = machine-local facts.
- Cross-machine rule: durable/cross-machine truth goes in the in-repo vault or
CLAUDE.md(both committed); nativememory/is machine-local and does NOT sync.
§8 — Native memory seed (machine-local)
- Append to
MEMORY.md(this machine): project uses Unity DOTS + Netcode for Entities; the chosen memory stack (vault + basic-memory + serena, claude-context fallback); that/dots-devis the dev driver and this setup is one-time. (Repeat on the other machine, or re-derive fromCLAUDE.md.)
Done-when
- All four DOTS packages installed, console clean, smoke-test
NetCodeTestWorldgreen. Assets/_Projectasmdef split compiles; client+server worlds spin up.- Vault scaffolded; obsidian-cli reads it; basic-memory recalls a note; serena resolves a symbol (or fallback recorded).
CLAUDE.md+ committed.mcp.json(portable) exist.- Second machine reproduces from §0 alone (everything else is in git).