Documentation technique pour Claude Code (claude.ai/code).
Command and Conquer - RTS 2D - Educational RTS project recreating Command and Conquer in 2D with Unity 6.
- Engine: Unity 6
- Pipeline: Universal Render Pipeline (URP) 2D
- Language: C# with .NET Standard 2.1
- Input: New Input System (NOT legacy Input class)
Branch: master
Phase: 🏗️ Building & Production System (Phase 1/5)
- ✅ Grid system (20×20, 1.0 unit cells, pathfinding 8 directions)
- ✅ Camera controller (WASD, edge scroll, zoom)
- ✅ 2 units: Buggy (speed 4.0), Artillery (speed 1.5)
- ✅ Selection system (single click + drag-box multi-selection)
- ✅ Corner bracket selection visual (white L-brackets)
- ✅ Animated cursor system (hover 6 frames, move 4 frames)
- ✅ 8-direction animation system (DirectionType, VehicleAnimator)
- ✅ State machine movement (Idle, Moving, WaitingForNextCell, Blocked)
- ✅ Atomic cell reservation (prevents race conditions)
- ✅ Collision detection with retry mechanism
- ✅ Component-Based (Nov 2025) - 100% composition, zero inheritance
- Eliminated Controllers, Contexts, UnitBase abstract class
- New units created 100% in Unity Editor (zero code)
- ~600 lines of code eliminated
- ✅ Generic components: Unit, VehicleMovement, SelectableComponent, VehicleAnimator
- Phase 1: Core Building System (multi-cell occupation) 🔨
- Phase 2: Production System (queue + timer)
- Phase 3: Spawn System (unit spawning at exit points)
- Phase 4: Building Placement (ghost preview with validation)
- Phase 5: UI Production Panel (sidebar + buttons + queue display)
First Building: Construction Yard (2×2) producing Buggy and Artillery Resources: None (time-based production only) Placement: Ghost preview with visual feedback (green=valid, red=invalid)
See docs/BUILDINGS.md for detailed implementation plan.
CommandAndConquer/
├── Core/ # Interfaces (IMovable, ISelectable), types (UnitData, GridPosition)
├── Grid/ # Grid system (depends on Core)
├── Camera/ # RTS camera (minimal dependencies)
├── Gameplay/ # Selection, cursor (depends on Core, Grid)
├── Units/ # Unit implementations
│ ├── Common/ # Generic components (Unit, VehicleMovement, etc.)
│ ├── Buggy/ # Buggy-specific assets
│ └── Artillery/ # Artillery-specific assets
├── Buildings/ # 🆕 Building system (construction, production)
│ ├── Common/ # Generic components (Building, ProductionQueue, SpawnPoint)
│ └── ConstructionYard/ # First building (2×2)
├── UI/ # 🆕 UI system (production panel, buttons, queue display)
│ ├── Scripts/
│ └── Prefabs/
└── Map/ # Terrain, tilemap
Core → Grid, Camera, Gameplay, Units, Buildings, Map, UI
Grid → (no deps)
Gameplay → Core, Grid
Units/Common → Core, Grid
Buildings/Common → Core, Grid
UI → Buildings
Principle: Pure composition. Units = assembly of components in Unity Editor.
Configuration:
- 20×20 cells, 1.0 unit each
- Conversion: Grid (5,5) → World (5.5, 5.5) - always +0.5f
- Pathfinding:
GridPathfinder.CalculateStraightPath()(8 directions)
Key Methods:
// Lifecycle
bool RegisterUnit(Unit unit, GridPosition pos) // Call in Start()
void UnregisterUnit(Unit unit) // Call in OnDestroy()
// Movement (ATOMIC - prevents race conditions)
bool TryMoveUnitTo(Unit unit, GridPosition newPos) // Reserves cell atomically
// Query
bool IsCellAvailableFor(GridPosition pos, Unit unit) // Check availabilityTryMoveUnitTo() for movement. IsCellAvailableFor() does NOT reserve!
Coordinate Conversion:
// Grid → World (+0.5f)
Vector3 worldPos = new Vector3(gridPos.x + 0.5f, gridPos.y + 0.5f, 0);
// World → Grid (FloorToInt)
GridPosition gridPos = new GridPosition(
Mathf.FloorToInt(worldPos.x),
Mathf.FloorToInt(worldPos.y)
);Pattern: 100% Composition
GameObject "Buggy"
├── Unit (generic)
├── VehicleMovement (generic)
├── SelectableComponent (generic)
├── VehicleAnimator (generic)
└── SpriteRenderer
Creating New Unit (zero code):
- Create → Command & Conquer → Unit Data
- Create GameObject
- Add components: Unit, VehicleMovement, SelectableComponent, VehicleAnimator, SpriteRenderer, BoxCollider2D
- Create Prefab → Done!
See GUIDE.md for detailed workflow.
State Machine:
enum MovementState { Idle, Moving, WaitingForNextCell, Blocked }Flow:
MoveTo(GridPosition)on Unit- Path calculation via
GridPathfinder.CalculateStraightPath() - Atomic reservation with
TryMoveUnitTo() - Interpolation with
Vector3.MoveTowards() - If cell occupied →
WaitingForNextCell(retry 0.3s × 20 = 6s timeout)
Debug Colors (BuggyMovementDebug): White=Idle, Green=Moving, Orange=Waiting, Red=Blocked
Architecture:
Unit (events) → SelectableComponent (coordinator) → CornerBracketSelector (display)
Multi-Selection (SelectionManager):
HashSet<ISelectable>for O(1) lookups- Drag box: 5px threshold,
Physics2D.OverlapAreaAll() - Single-click or drag-box
Visual Types:
SpriteColor(legacy) - Color changeCornerBrackets(default) - White L-brackets in 4 corners
Corner Rotations: TL=0°, TR=-90°, BR=180°, BL=90°
RTS camera with WASD, edge scrolling, zoom (mouse wheel).
Files: Camera/Scripts/CameraController.cs, CameraBounds.cs (ScriptableObject)
Types:
- Default - System cursor
- Hover - 6 frames @ 10 FPS (units)
- Move - 4 frames @ 10 FPS (destinations)
Priority: Hover > Move > Default
Setup: Sprites must have isReadable = true (auto-configured by CursorSpriteImporter)
Key Methods:
CursorManager.SetCursor(CursorType type)
CursorManager.ResetCursor()8 Directions: E, NE, N, NW, W, SW, S, SE (45° each)
Components:
DirectionType- EnumVehicleAnimationData- ScriptableObject (8 sprites)VehicleAnimator- Passive polling component
Pattern: Polls VehicleMovement in Update(), updates sprite only on direction change.
Setup: See docs/ANIMATION.md
Pattern: 100% Composition (like Units)
GameObject "ConstructionYard"
├── Building (generic)
├── ProductionQueue (generic)
├── SpawnPoint (generic)
└── SpriteRenderer
Key Components:
// BuildingData.cs - ScriptableObject
- string buildingName
- int width, height // Multi-cell size (2×2, 3×2, etc.)
- ProductionItem[] canProduce // What this building produces
- Vector2Int spawnOffset // Exit point for units
// Building.cs - Component
- BuildingData data
- GridPosition[] occupiedCells
- ProductionQueue productionQueue
- SpawnPoint spawnPoint
// ProductionQueue.cs - Component
- Queue<ProductionItem> queue
- float currentProgress // 0.0 to 1.0
- void AddToQueue(ProductionItem)
- event OnItemCompleted
// ProductionItem.cs - ScriptableObject
- string itemName
- float productionTime // In seconds
- GameObject prefab
- bool isBuilding // Building or unitGrid Extensions (multi-cell):
// GridManager.cs [NEW METHODS]
bool CanPlaceBuilding(GridPosition origin, int width, int height)
bool TryOccupyBuildingCells(Building, GridPosition origin, int w, int h)
void ReleaseBuildingCells(Building)Production Flow:
- User clicks UI button → AddToQueue()
- ProductionQueue.Update() advances timer
- OnItemCompleted → if unit: SpawnPoint spawns it, if building: placement mode
- SpawnPoint verifies cell is free before spawning
Building Placement:
- Ghost preview follows mouse (transparent sprite)
- Visual feedback: green=valid, red=invalid
- Left-click confirms, right-click cancels
- Validates all cells are free before placement
See docs/BUILDINGS.md for detailed documentation.
CRITICAL: Use New Input System only!
// ❌ WRONG
if (Input.GetKeyDown(KeyCode.Space)) { }
// ✅ CORRECT
using UnityEngine.InputSystem;
if (Keyboard.current.spaceKey.wasPressedThisFrame) { }Use FindFirstObjectByType<T>() (Unity 6 API):
gridManager = FindFirstObjectByType<GridManager>();- PPU: 128
- Filter Mode: Point
- Compression: None
- 128px = 1.0 Unity unit = 1 grid cell
- Open
Assets/_Project/Scenes/Game.unity - Press Play
▶️
Zero code workflow (5 minutes):
- Create UnitData asset
- Create GameObject + Add components
- Create Prefab
See GUIDE.md for step-by-step instructions.
<type>: <message>
Types: feat, fix, refactor, docs, chore, test
Example: feat: add Tank unit with heavy armor
/test-game- Launch Game scene
git status
git add . && git commit -m "feat: description"
git log --oneline -5/gen-commit- Generate commit message
| Issue | Solution |
|---|---|
| Input System errors | Use UnityEngine.InputSystem API |
| Sprite not centered | Always add +0.5f offset |
| Assembly errors | Add dependency in .asmdef |
- Coordinate system: Grid = integers, World = floats (+0.5f)
- State machines: See
VehicleMovement.csfor pattern - New Input System only: Never use legacy
Input - Assembly Definitions: Check dependencies before adding references
- Debug with Gizmos: Use
OnDrawGizmos()for visualization - Test frequently: Use
/test-game+ numpad controls
| Item | Value |
|---|---|
| Grid | 20×20 cells, 1.0 unit, +0.5f centering |
| Sprites | 128 PPU, Point filter |
| Input | New Input System (UnityEngine.InputSystem) |
| Managers | FindFirstObjectByType<T>() |
| Commits | type: message |
Last Updated: 2025-11-24 Current Focus: Building & Production System (Phase 1/5 - Core Building System) Next Milestone: Construction Yard with production queue for Buggy and Artillery
Documentation:
- GUIDE.md - Developer guide (architecture, systems, workflows)
- CHANGELOG.md - Change history
- docs/BUILDINGS.md - 🆕 Building system implementation plan (5 phases)
- docs/ - Technical documentation (UNITS, TOOLS, ANIMATION, BUILDINGS)