7.0 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
Nox is a Unity 6 RPG game (product name "Nox", Windows build target Nox.exe). Party-based gameplay with Addressables for asset management, Newtonsoft JSON for serialization, URP 17.3.0 for rendering, and Unity Input System 1.18.0.
Build & Development
- Unity version: 6.0.3 (C# 9.0, .NET Framework 4.7.1)
- Build output:
Builds/Nox.exe - No CI/CD pipeline — builds are done through Unity Editor
- No test suite exists —
com.unity.test-frameworkis in manifest but unused - Scene authoring: Individual scenes can be played standalone via
SceneReferencecomponent
Architecture
Dual-Layer State Management
Two layers of state drive the application:
- Game States (
IGameState): Application-level flow —SplashGameState→MainMenuGameState→GameModeGameState- Lifecycle:
EnterGameState()→Tick()/LateTick()→ExitGameState()→Dispose()
- Lifecycle:
- Play Modes (
IPlayMode): Gameplay modes within GameMode — Adventure, Town, Rest, Combat, PauseMenu- Lifecycle:
EnterPlayMode()→Tick()/LateTick()→ExitGameMode()→Dispose()
- Lifecycle:
GameModeGameState bridges these layers, managing play mode transitions and scene loading via Addressables. GameStateRunner (MonoBehaviour) drives the update loop and handles fade-in/fade-out transitions via ISceneTransition.
Boot Sequence
Boot.cs ([RuntimeInitializeOnLoadMethod]) → loads "Initializer" prefab via Addressables → EntryPoint.cs (MonoBehaviour) loads all config ScriptableObjects, creates game states, initializes platform subsystems and character systems → GameStateRunner begins ticking states.
In editor, Boot.cs checks BootMode preference (Full Boot, Scene Boot, Unity Default).
GameDataState
Central state container holding current GameState, PlayMode, ActiveParty, platformSelector, activeSessionId, and savedPartyPosition. State changes via ChangeGameState() and ChangePlayMode().
Character System
Factory-based architecture with ScriptableObject configuration:
DefaultCharacterSystemsFactory.Create()
├─ PerkFactory (PerkRegistry ScriptableObject)
├─ CharacterAttributesFactory (validates attributes)
├─ CharacterStatsFactory (derives stats from attributes)
├─ CharacterFactory (creates from templates or custom requests)
└─ PartyFactory (assembles: 1 protagonist + companions)
- Data:
EntityAttributes(might, reflex, knowledge, perception) →EntityStats(health, stamina, level, experience) - CharacterDefinition: ID, DisplayName, Attributes, Stats, Race, Class, Role (Protagonist/Companion), Perks, Modifiers
- Config ScriptableObjects:
CharacterBaseSettings,PerkRegistry,CharacterRegistry - Key interfaces:
ICharacterSystems,ICharacterFactory,IPartyFactory,IPerkFactory
Persistence
GamePersistenceController + Jovian.SaveSystem with JSON serialization to Application.persistentDataPath. Save data model: NoxSavedDataSet (activePlayMode, partyDefinition, partyPosition, adventureData). Save slots managed by SaveSlotManager.
Platform Abstraction
IPlatform with DesktopPlatform and UnityEditorPlatform. Each initializes platform-specific IInput (DesktopInput/EditorInput using Unity InputSystem generated code).
Addressables Asset Keys
Assets loaded by string key: "Initializer", "AdventureMapPrefabs", "PauseMenuPrefabs", "AdventureSettings", "CharacterBaseSettings", "PerkRegistry", "CharacterRegistry", "BootstrapReferences".
Namespace Convention
Namespaces mirror folder structure: Nox.Core, Nox.Game, Nox.Input, Nox.Platform, Nox.Util.
Code Layout
Assets/Code/
├── Core/ # Boot, EntryPoint, GameStateRunner, IGameState, IPlayMode, GameDataState
├── GameState/
│ ├── Camera/ # CameraController, CameraSettings
│ ├── Entities/ # Character/Party/Perk factories and registries
│ ├── PlayModes/ # AdventurePlayMode, PauseMenuPlayMode, stubs for Town/Rest/Combat
│ └── UI/ # View implementations (PauseMenu, Adventure views)
├── Input/ # IInput abstraction, Desktop/Editor implementations
├── Platform/ # IPlatform, DesktopPlatform, UnityEditorPlatform
├── SplashMainMenuUI/
└── Util/ # BootMode editor utility
C# Style (from .editorconfig)
- 4 spaces, LF line endings
varpreferred (csharp_style_var_*: true:suggestion) — usevarwhen type is apparent- Target-typed
newwhen type is evident (CharacterDefinition c = new()) - No space after keywords in control flow (
if(,for(, notif () - Opening braces on same line (
csharp_new_line_before_open_brace = none) else/catch/finallyon new line after closing brace- Block-scoped namespaces (
namespace Foo { ... }) - Always use braces (
csharp_prefer_braces = true) - Naming: PascalCase for types/methods/properties, camelCase for all fields (public and private),
Iprefix for interfaces - Expression-bodied: yes for properties/accessors/indexers/lambdas; no for constructors/methods/operators/local functions
- No
this.qualifier - Use language keywords over BCL types (
intnotInt32)
Patterns
- Constructor-based dependency injection (no DI container)
- ScriptableObject-based configuration loaded via Addressables
- Factory pattern for character/party creation
- Action delegates for UI event communication (e.g.,
menuGameStateData.startGameRequests += handler) - Mixed async patterns: both
async TaskandIEnumeratorcoroutines for async operations
Planning Docs Convention
Non-trivial features are planned in docs/plans/ as paired markdown files: a design doc and an implementation doc, both prefixed with the date. Examples: 2026-04-05-ingame-logging-design.md + 2026-04-05-ingame-logging-implementation.md, 2026-04-06-popup-system-design.md + 2026-04-06-popup-system-implementation.md. When starting a new feature, look here first for existing context, and follow the same pair-of-docs pattern for new work.
In-House Jovian Packages
Several packages under Packages/ are first-party code maintained alongside the game, not third-party dependencies. Before adding new capabilities, check whether one of these already provides what you need:
Jovian.SaveSystem— JSON persistence, used byGamePersistenceControllerJovian.Calendar— custom in-game calendar systemJovian.InGameLogging— runtime logging surfaceJovian.EncounterSystem— data-driven encounter authoring,IEncounterKindpolymorphic payloads,EncounterLinkcross-table refs,QuestProgressgated progression +QuestLog. Designer browser atJovian → Encounters → Encounter Browser.Jovian.PopupSystem— popup/dialog UIJovian.ZoneSystem— zone/region managementJovian.Logger— developer loggingJovian.InspectorTools/JovianUtilities— editor and general utilities