Dev notes ·

Starting the Unity game from scratch

What already existed
  • Plan: embersofolympus-game/plan-version-2/ — README.md (design decisions), development-plan.md (phase-by-phase build order with gates).
  • embersofolympus-unity\My project on the NAS: only the default Unity 6 URP template (URP 17.3, Input System, AI Navigation, AI Assistant pre-release). No game code, no git repo.
The plan we agreed on
  1. Work on a local drive, not the NAS or OneDrive (Unity's Library/ hates SMB/sync). NAS = git remote/backup.
  2. Fresh Unity 6 LTS project, Universal 3D (URP) template, named EmbersOfOlympus.
  3. Repo hygiene: git init, Unity .gitignore, Visible Meta Files + Force Text, Git LFS for binaries, first commit = empty project.
  4. Folder skeleton: Assets/_Project/{Art,Audio,Code/Runtime,Code/Editor,Data, Prefabs,Scenes,UI,Localization} + Assets/ThirdParty; namespace EmbersOfOlympus.*.
  5. Phase 0 grey-box loop (capsules/cubes): third-person movement + camera → one NavMesh enemy → tab-target combat (GCD + one skill) → loot/inventory/equip. Items, affixes, skills, enemies = ScriptableObjects. Gate: is it fun with cubes?
  6. Vertical slice: one class, one zone, one boss end-to-end, then replicate.
Status
  • User created the new project in Unity Hub; waiting for Unity to open it.
  • Waiting on: the project path from the user (must not be in OneDrive/NAS).
  • Next for Claude (with the editor closed): .gitignore, .gitattributes (LFS), folder skeleton, first movement/camera script.
  • Suggested to the user: run git lfs install.
Project created
  • Path (user's choice): the shared drive on the NAS, not a local drive. Expect slower imports. Watch for file-lock errors.
  • Editor: Unity 6000.3.24f1 (D:\Programs\Unity\Editor\6000.3.24f1), URP 17.3, Input System 1.20, AI Navigation 2.0, Test Framework 1.6. Template leftovers (TutorialInfo/, Readme.asset) are still there.
  • No git yet, on the user's instruction.
Added .claude/ to the project (Unity ignores it; it's outside Assets/)
  • .claude/CLAUDE.md: project rules, key paths, skill index.
  • .claude/settings.json: blocks Claude from editing Library/, Temp/, Logs/, UserSettings/ and any .meta file.
  • .claude/skills/:
    • embers-design-lookup: which plan-v2 doc answers what; phase/gate discipline.
    • unity-csharp-script: code layout, asmdefs, conventions, Unity 6 API notes, the "In Unity, do this" hand-off.
    • unity-data-definitions: ScriptableObject definition vs runtime instance; loot rolling.
    • unity-editor-tooling: Editor scripts/menu items instead of hand-editing YAML.
    • unity-assets-meta: .meta/GUID safety, folder layout, asset-ledger rule.
    • unity-compile-check: read Editor.log, or batch mode when the editor is closed.
    • unity-tests: Edit/Play Mode test asmdefs and batch-mode test runs.
    • embers-localization: narrative.csv vs systems.csv, key rules.
    • embers-notes-log: how to keep this file.
Found
  • Docs disagree on the ranged class name: README says Archer, skill-trees.md says Huntress. The user needs to pick one before that class is coded.
Next
  • Phase P Step 3: create the Assets/_Project/... folder skeleton, asmdefs and the two localization CSVs.
  • Then Phase 0 Step 5: movement + camera.
Project moved to the local disk
  • The user moved the project to D:\Dev\embers-of-olympus-unity, which is now the only working copy (as the plan recommends: Unity's Library/ and network/sync folders don't mix). The NAS path in the entries above is out of date.
  • Updated .claude/CLAUDE.md and the unity-compile-check, unity-tests and embers-notes-log skills to the new path, and removed the NAS-slowness notes.
  • The old copy at the shared drive still exists. Claude left it untouched. The user decides whether to delete it.
  • Design docs, the asset ledger and this notes file stay on the NAS.
Fixed: console errors after opening the project
  • error CS0117: 'BuildTarget' does not contain a definition for 'ReservedCFE' in Library/PackageCache/com.unity.inputsystem/.../InputSystemPluginControl.cs.
    • Cause: the project was created from an old template bundled with the editor (3d-cross-platform-17.0.14, made for Unity 6.0), so Packages/manifest.json pinned Unity 6.0-era versions. Unity 6.3 auto-upgraded URP (tied to the editor) but left Input System at 1.12.0, which uses a build target Unity 6.3 removed.
    • Fix: set Packages/manifest.json to the Unity 6.3 versions: Input System 1.20.0, URP 17.3.0, AI Navigation 2.0.14, Test Framework 1.6.0, Timeline 1.8.13, Visual Scripting 1.9.12, Rider 3.0.40, Visual Studio 2.0.26, Collab Proxy 2.13.6.
    • Lesson: never edit files in Library/PackageCache. Fix the version in the manifest.
  • Error reason is 'NoSubscription' (generators.ai.unity.com): these are log messages, not compile errors. They come from the Unity AI Assistant package (com.unity.ai.assistant, a pre-release) checking for a Unity AI plan. Left as is, pending the user's choice: keep it (and subscribe) or remove the package.
  • Added both cases to the unity-compile-check skill's error table.
  • Second attempt: the user removed the AI Assistant and Sentis packages in Package Manager. Unity then rewrote manifest.json from its own copy, which put the old versions back (Input System 1.12.0) before it had resolved the new ones. Claude re-applied the 6.3 versions and kept the AI packages removed.
    • Lesson: after Claude edits manifest.json, let Unity finish resolving packages before changing anything in Package Manager. Otherwise Unity overwrites the edit.
  • Verified fixed (18:50): Editor.log shows Package Manager registered (email removed), then "Reloading assemblies… Mono: successfully reloaded assembly" with no error CS after it. packages-lock.json agrees (1.20.0). The project now compiles cleanly.
  • Seen in the log, not acted on: repeated Curl error 60: Cert verify failed… CN does not match. Some Unity web request gets a certificate for the wrong host, usually antivirus/firewall HTTPS scanning or a proxy. Packages still downloaded fine, so it doesn't block anything. Revisit only if Asset Store/package downloads fail.
Decision: class names
  • Hoplite, Huntress, Oracle (user, 2026-10-10). README's "Archer" is outdated. Recorded in .claude/CLAUDE.md and the embers-design-lookup skill. (Plan-v2 README not edited. The user may want to update it there too.)
Phase P, Step 3: project skeleton (done)
  • Folders: Assets/_Project/{Art,Audio,Code,Data,Localization,Prefabs,Scenes,UI} and Assets/ThirdParty/.
  • Assembly definitions (they split the code into separate DLLs, so a change recompiles less and test code stays out of the game):
    • Code/Runtime/EmbersOfOlympus.Runtime.asmdef (refs Input System, AI Navigation, TextMeshPro, UGUI)
    • Code/Editor/EmbersOfOlympus.Editor.asmdef (Editor only)
    • Code/Tests/EditMode/…Tests.EditMode.asmdef, Code/Tests/PlayMode/…Tests.PlayMode.asmdef
  • Localization tables, kept separate from day one (README §4.2):
    • Localization/Resources/Localization/narrative.csv: story text (npc.chiron.name so far)
    • Localization/Resources/Localization/systems.csv: UI text (title, the three class names, Health, +{0} Damage)
    • A Resources folder, so the game loads them with no Inspector wiring.
  • First game code: Code/Runtime/Localization/CsvTable.cs (CSV parser handling quotes, commas and newlines in text) and Loc.cs (Loc.Get("key"), English fallback, #key# + warning for missing keys).
  • 12 Edit Mode tests in Code/Tests/EditMode/Localization/.
  • Compiled cleanly (Editor.log 18:52: Runtime and Tests.EditMode DLLs built, no errors). Tests are not run yet: the user runs them in Test Runner.
  • Skills updated: embers-localization (real paths, class. prefix, Loc API).
Art question from the user
  • The user offered Blender or AI tools for art. Answer: no art yet. Phase 0 is deliberately grey-box (capsules and cubes) until Gate 0 says the loop is fun. Art starts in Phase 1, Step 13 (buy character/environment packs + Mixamo; Blender for cleanup; AI for 2D: icons, UI, textures, concept). Every AI asset gets an asset-ledger row.
  • Useful now, optional: concept art / mood boards for Myrra, Eleusis and the Rarian Plain, to guide the later pack shortlist (Step 4).
Next
  • The user runs the tests (Window → General → Test Runner → EditMode → Run All).
  • Then Phase 0, Step 5: third-person movement + camera.
  • (Update) The user ran the tests: all 12 green. Phase P done.
Phase 0, Step 5: movement & camera (code written, waiting on the user to play)
  • Code/Runtime/Player/PlayerInputReader.cs: controls defined in code (no .inputactions wiring): WASD/arrows/left stick = move, mouse delta + right stick = look, RMB = steer (camera + character turn together), LMB = orbit (camera only), scroll = zoom. The only place that touches the Input System.
  • Code/Runtime/Player/PlayerMotor.cs: CharacterController. Moves relative to the camera with acceleration/deceleration (feels weighty but responsive) and turns toward the run direction. With RMB held it faces the camera, so A/D strafe and S backpedals at 60%, as in WoW. Gravity with a small "stick to ground" push for slopes and steps. All feel numbers are Inspector tunables with tooltips.
  • Code/Runtime/Player/MovementMath.cs: pure maths (camera-relative direction, backpedal speed), split out so it's unit-testable. 6 new Edit Mode tests.
  • Code/Runtime/CameraRig/ThirdPersonCamera.cs: spring-arm camera.
    • Yaw/pitch with clamps; cursor hides and locks while a mouse button is held.
    • Scroll zooms in 1.5 m notches (2–18 m) with smoothing. It uses only the scroll sign, because the raw value differs per platform.
    • Sphere-cast collision: snaps in instantly when a wall blocks, eases back out.
    • Slight follow smoothing.
    • The folder is CameraRig/, not Camera/: a namespace called Camera would hide UnityEngine.Camera. Added to the unity-csharp-script skill.
  • Code/Editor/GreyboxSceneBuilder.cs: menu Embers → Setup → Create Grey-box Scene builds Scenes/SCN_Greybox.unity:
    • an 80 m ground, a wall, boxes, a 15° ramp to a platform, 0.3 m stairs and a column row (to test the camera and slopes);
    • an orange capsule Player with a "nose" showing facing, and the camera;
    • 3 grey-box materials in Art/Materials/, and the scene first in Build Settings.
  • Known for later: LMB = orbit will need "click = select target, drag = orbit" when tab-target arrives (Step 6).
  • Not compiled yet when written (Unity window not focused). Check on the next turn.
  • (Update, same day) Checked against the new project at D:\Dev\embers-of-olympus-unity: all Step 5 files are in place and compile cleanly (Editor.log: Runtime, Editor and EditMode tests built, no errors or warnings).
  • Added the WoW "both mouse buttons = run forward" in Code/Runtime/Player/PlayerMotor.cs.
  • User confirmed: hold RMB to orbit like WoW (RMB = camera + character turn, LMB = camera only). This matches what was built.
  • Scene name: the builder uses SCN_Greybox, while CONVENTIONS.md gives Greybox_Loop as an example. Left as is; rename later if the user prefers.
  • (Update) The user ran Embers → Setup → Create Grey-box Scene and pressed Play: the capsule moves. Step 5 works. Feel tuning still open (the user's call).
Phase 0, Step 6: target & basic attack (code written, waiting on the user to play)
  • User judged Step 5 movement/camera: feels fine, no tuning needed.
  • Code/Runtime/Player/PlayerInputReader.cs: new actions: Tab (gamepad RB) = next target, Esc = clear target, 1 (gamepad X/west) = attack, mouse position, and "LMB pressed this frame" for click-selection.
  • Code/Runtime/Combat/ (new folder, namespace EmbersOfOlympus.Combat):
    • DamageInstance.cs: one hit (amount + source). Step 7 grows it (type, crit, stats).
    • Health.cs: ApplyDamage(DamageInstance) is the only way to lower health (coding rule 2). Raises Damaged and Died (once). Step 7 puts Stats/mitigation in front of it.
    • Targetable.cs: marks selectable enemies; static registry so targeting never searches the scene. Ring radius + "feet position" for the ring.
    • TargetingMath.cs: pure Tab logic: in range (30 m), in front of the camera wins over behind, nearest first, pressing again cycles. Height is ignored.
    • TargetSelector.cs (on Player): Tab / left-click / Esc; drops dead targets. Click-select reads the cursor in Update, before the camera locks it in LateUpdate, so LMB = click-select and LMB-drag = orbit both work.
    • BasicAttack.cs (on Player): hold 1 → hits the target once per 1.5 s GCD, turns to face it, 3 m melee range, 10 damage. Console messages for no target / out of range / each hit. Values are grey-box placeholders → Stats (Step 7) and skill data (Step 11).
    • TargetRing.cs: gold LineRenderer circle under the current target.
    • DamageFlash.cs: enemy flashes white and swells 12% on each hit (first game-feel).
    • DestroyOnDeath.cs: enemy disappears 0.25 s after dying.
  • Code/Editor/GreyboxSceneBuilder.cs: now also adds TargetSelector + BasicAttack to the Player, three red cube enemies (50 HP each) and the TargetRing; two new materials (M_Greybox_Enemy, M_Greybox_TargetRing with URP Unlit).
  • Tests: Tests/EditMode/Combat/TargetingMathTests.cs (6) and HealthTests.cs (4).
  • Unity hit a compile error (CreateMaterial takes 3 arguments) because it compiled between two of my edits; the file was fixed 3 s later. Recompile pending (Unity needs focus).
Decisions
  • Damage entry point lives on Health for now (not a separate Stats yet): Step 6 needs a thing that dies; Step 7 adds Stats without changing any caller.
  • Attack on key 1 (hotbar slot 1), held = repeat on GCD. No auto-attack yet.

All dev notes