This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
A Unity project (Editor version 6000.3.7f1, Universal Render Pipeline, 2D/top-down via Physics2D) that
procedurally generates a maze of connected rooms and populates it with autonomous agents that explore it. All
project-specific code lives under Assets/Scripts/Maze/, namespace MazeGen. There is no code outside that
folder worth touching except Assets/Scenes/SampleScene.unity, which wires up the single MazeSceneBuilder
entry point component.
This is a pure Unity Editor project — there is no CLI build, lint, or test setup in the repo (no package.json,
Makefile, .asmdef, or test assemblies). The only way to run/verify changes is:
6000.3.7f1 (or compatible 6000.3.x).Assets/Scenes/SampleScene.unity.MazeSceneBuilder component on the scene's root object generates the maze and spawns
agents automatically.Compile errors surface in the Unity Console; there's no separate dotnet build/csc step to invoke. If you
need to sanity-check C# syntax without the Editor, treat the generated Assembly-CSharp.csproj as a rough
reference for compiled files, but it's Editor-generated and shouldn't be hand-edited.
The maze is not a pre-built grid — it's a lazily-grown graph of Room nodes connected by Exit doors,
generated on demand as agents actually walk through unresolved exits. Nothing beyond an unused exit exists
until something tries to go through it. This is what makes "many agents, huge maze" cheap.
Core/)Room — a node with Position (free Vector2, not grid-snapped), Radius, Kind (Start/Normal/Hallway/Exit),
and a list of Exits. CorridorWaypoints is set only on elbow-hallway rooms (see below) for stretched
rendering.Exit — one doorway. Grid-locked to the 4 cardinal directions (0/90/180/270°, DirectionDegrees), so a
room has at most one exit per side and "the door facing room X" always has a single, exact answer. Exits are
matched in connected pairs (ConnectedRoomId/ConnectedExitId) once resolved; IsUsed marks that.MazeGraph — the registry of all rooms, id allocation, UnusedExitCount bookkeeping (must never hit 0
before an Exit room exists, or the maze could never be solvable), and spatial lookup via SpatialRoomIndex
(a uniform grid bucket index, cell size = roomSpacing, used for overlap/collision queries — not a maze grid).Generation/)MazeGenerationSettings — a ScriptableObject with all tunables (room sizes, exit counts, hallway chance,
start room count/spread, collision-avoidance search parameters, exit-room eligibility odds).MazeGenerator — the core algorithm, called lazily from MazeAgentController.TryUseExit /
AutonomousAgentBrain whenever an agent uses an unresolved exit (GenerateConnectedRoom). On each call it:
fromRoom.Position + exit.Direction * roomSpacing).TryConnectViaExistingDoor: if that spot overlaps an existing room, looks for (or adds on-the-fly) a
door on that room facing back toward fromRoom, and links into it instead of creating an overlapping
room — this is what turns the tree into a maze with loops. The link is either direct (ConnectStraight,
doors face each other head-on) or via a single 90°-bend elbow hallway room (ConnectWithElbow,
perpendicular doors). All paths run IsPathClear (point-to-segment distance vs. every other room) so a
corridor can never cut through unrelated geometry.TryRouteAroundObstruction tries
extending further out, then a single 90° bend, before falling back to FindClearPosition (a ring/spiral
search) as a last resort.BuildRoom, rolling cardinal-direction exits (PickCardinalAngles).Visualization/)MazeSceneBuilder — the scene entry point ([RequireComponent(MazeGenerator)]). Generates the configured
start rooms, spawns agentCount agents on staggered coroutine delays, wires each agent's
AutonomousAgentBrain, tracks win conditions (target finished-agent count and/or a time limit — at least one
must be set, else it warns and defaults to requiring all agents), and draws a simple IMGUI HUD (elapsed
time/finished count, a clickable agent list that makes the camera follow one, a "zoom to fit maze" button).RoomView — placeholder square sprite per room; renders elbow hallways as stretched/rotated rectangles along
CorridorWaypoints instead of a single small square.ExitMarker — placeholder door sprite. Purely informational (not clickable — movement is autonomous now):
green/blue/gray coloring is relative to whichever agent the camera is currently following.PathVisualizer — one LineRenderer per hop; only the followed agent's trail is shown, with the most recent
hop bright and earlier hops dimmed.Agent/)MazeAgent — plain C# (no MonoBehaviour) state: current room, path history, visited-room/used-exit sets,
IsFinished. Cheap enough to run many of.MazeAgentController — scene-facing wrapper: positions a GameObject, tints it a per-agent color, and drives
TryUseExit (which calls MazeGenerator.GenerateConnectedRoom lazily if the exit isn't resolved yet).AutonomousAgentBrain — per-agent decision loop. Waits a randomized initial delay (so agents don't all
decide in lockstep), then ticks a steady decisionInterval. ChooseExit is explore-biased: prefers an
unused exit (fresh territory) > a used exit into a room this agent hasn't personally visited (following
another agent's discovery) > backtracking into an already-visited room, with exploreChance adding
randomness. This is the intended extension point for smarter decisions later (e.g. "peek" a room and weigh
danger before choosing).Camera/, Input/)MazeCameraController — manual WASD pan / middle-mouse drag, plus FocusOn (smooth glide, used only while
following an agent) and FrameBounds (instant zoom-to-fit, used by the HUD button). The camera does nothing
on its own unless something calls one of those.MazeInput — input-backend-agnostic helpers (ENABLE_INPUT_SYSTEM vs legacy Input), since this project has
the Input System package installed and legacy APIs like OnMouseDown/Input.GetKey silently break if Active
Input Handling is set to "Input System Package (New)" only.RoomView, ExitMarker, agent sprites) are intentionally flat placeholder sprites sharing
RoomView.SharedSquareSprite — swappable for real art later without touching generation logic.