Zero-Day Attack Project Architecture
Expert knowledge of the Zero-Day Attack Unity codebase structure, design patterns, and architectural decisions.
Design Principles
1. Separation of Concerns
The codebase organizes into distinct layers:
| Layer |
Location |
Purpose |
| Data |
Core/Data/ |
Immutable data structures, ScriptableObjects |
| State |
Core/State/ |
Mutable runtime game state |
| Logic |
Core/GameManager.cs |
Game rules, orchestration |
| View |
View/ |
Visual representation, Unity components |
| Input |
Input/ |
Board SDK abstraction |
| Config |
Config/ |
Static layout constants |
CRITICAL - State Ownership:
| Component |
Owns |
Does NOT Own |
GameState |
Token positions, game phase, turn |
Visual representations |
TokenManager |
TokenView instances, visuals |
Token positions in game state |
GameManager |
Game rules, state transitions |
View updates |
Anti-pattern: View layer (TokenManager) directly updating GameState or making game logic decisions. Always route state changes through GameManager.
2. Board SDK Isolation
Only InputManager.cs imports Board.Input namespace. This:
- Prevents SDK types leaking throughout codebase
- Enables testing without hardware
- Centralizes coordinate conversion
3. Singleton Managers
Core systems use singleton pattern with Instance property:
GameManager.Instance // Game state and logic
TileManager.Instance // Tile spawning, positioning
TokenManager.Instance // Token spawning, input handling
InputManager.Instance // Board SDK event broadcasting
4. ScriptableObject Databases
Game data stored in ScriptableObjects:
TileDatabase - 25 tile definitions with sprites and paths
TokenDatabase - 6 token definitions with sprites and glyph IDs
Namespace Organization
| Namespace |
Purpose |
ZeroDayAttack.Config |
Layout constants (LayoutConfig) |
ZeroDayAttack.Core |
Game orchestration (GameManager) |
ZeroDayAttack.Core.Data |
Data structures, enums, databases |
ZeroDayAttack.Core.State |
Runtime state classes |
ZeroDayAttack.View |
Visual components, managers |
ZeroDayAttack.Input |
Board SDK wrapper |
ZeroDayAttack.Diagnostics |
Debug utilities |
ZeroDayAttack.Editor |
Editor-only tools |
Namespace Rules
When creating new scripts:
- Place in appropriate namespace based on responsibility
- Use full namespace declaration:
namespace ZeroDayAttack.View { }
- Editor scripts:
ZeroDayAttack.Editor
- Test scripts: Match the namespace being tested
Folder Structure
Assets/Scripts/
├── Config/
│ └── LayoutConfig.cs # Static layout constants
│
├── Core/
│ ├── GameManager.cs # Game orchestrator singleton
│ ├── Data/ # Immutable data structures
│ │ ├── Enums.cs # EdgeNode, PathColor, Player, etc.
│ │ ├── PathSegment.cs # Path connection between nodes
│ │ ├── TileData.cs # Tile definition
│ │ ├── TileDatabase.cs # ScriptableObject: all tiles
│ │ ├── TokenData.cs # Token definition
│ │ └── TokenDatabase.cs # ScriptableObject: all tokens
│ └── State/ # Mutable runtime state
│ ├── BoardState.cs # Grid, reserves, deck
│ ├── GameState.cs # Phase, current player
│ └── TokenState.cs # Token position, ownership
│
├── View/ # Visual components
│ ├── TileManager.cs # Singleton: tile spawning
│ ├── TileView.cs # Individual tile visual
│ ├── TokenManager.cs # Singleton: token spawning
│ ├── TokenView.cs # Individual token visual
│ ├── BackgroundRenderer.cs # Board background
│ ├── CameraController.cs # Camera setup
│ └── GridOverlayRenderer.cs # Grid lines with glow
│
├── Input/
│ └── InputManager.cs # Board SDK wrapper (ONLY Board.Input)
│
├── Diagnostics/
│ └── SceneDiagnostic.cs # Runtime debug
│
└── Editor/
├── TileParser.cs # Menu: ZeroDayAttack > Parse Tiles
└── TokenParser.cs # Menu: ZeroDayAttack > Parse Tokens
Class Responsibilities
Core Layer
| Class |
Responsibility |
GameManager |
Initialize game, manage phases, orchestrate state. No direct visuals. |
GameState |
Hold BoardState, TokenState[], current player, phase, actions |
BoardState |
5×5 grid (TileData[,]), reserves, deck, discard |
TokenState |
Token identity, position (tile, node), physical tracking |
Data Layer
| Class |
Responsibility |
TileData |
Define tile: ID, sprite, segments, rotation, grid position |
TokenData |
Define token: ID, sprite, owner, type, glyph ID |
PathSegment |
Connect two EdgeNode values with PathColor |
TileDatabase |
ScriptableObject with List<TileData> |
TokenDatabase |
ScriptableObject with 6 token slots |
View Layer
| Class |
Responsibility |
TileManager |
Spawn tiles, grid-to-world conversion, hold TileDatabase |
TokenManager |
Spawn tokens, handle glyph events, snap to nodes |
TileView |
MonoBehaviour on tile GameObjects, manage sprite |
TokenView |
MonoBehaviour on token GameObjects, manage position |
BackgroundRenderer |
Render board background |
GridOverlayRenderer |
Draw 5×5 grid with glow effect |
CameraController |
Configure orthographic camera |
Input Layer
| Class |
Responsibility |
InputManager |
Poll BoardInput, fire events, coordinate conversion |
Data Flow
Board Hardware (touch/glyph)
│
▼
InputManager ← Only Board.Input import
│
┌────┴────┐
▼ ▼
TokenManager (Future: Tile touch)
│
▼
GameManager ← Game logic decisions
│
┌───┴───┐
▼ ▼
GameState TileManager
BoardState (spawn tiles)
TokenState
Event-Driven State Updates
GameManager should expose events for state transitions:
// GameManager events
public event Action OnSetupComplete;
public event Action<TokenState> OnTokenPlaced;
public event Action<TokenState> OnTokenMoved;
public event Action<Player> OnTurnChanged;
Flow Example (Token Placement):
InputManager detects glyph, fires OnContactBegan
TokenManager receives event, calls GameManager.PlaceToken()
GameManager validates placement, updates GameState
GameManager fires OnTokenPlaced event
TokenManager (subscribed) updates visual position
Scene Hierarchy
GameplayScene
├── MainCamera [CameraController]
├── GlobalLight2D
├── GameManager [GameManager]
├── TileManager [TileManager]
├── TokenManager [TokenManager]
├── InputManager [InputManager]
├── BackgroundRenderer [BackgroundRenderer]
├── GridOverlayRenderer [GridOverlayRenderer]
├── Tiles (spawned at runtime)
└── Tokens (spawned at runtime)
Coordinate Systems
Grid Coordinates
- Origin: (0, 0) = bottom-left of 5×5 grid
- Range: (0, 0) to (4, 4)
- Center tile: (2, 2)
World Coordinates
- Origin: (0, 0) = screen center = grid center
- Grid spans: -5.0 to +5.0 in X and Y
- Tile size: 2.0 world units
Conversion
// Grid to World (via LayoutConfig)
float x = LayoutConfig.GridLeft + (gridX * LayoutConfig.TileSize) + (LayoutConfig.TileSize / 2f);
float y = LayoutConfig.GridBottom + (gridY * LayoutConfig.TileSize) + (LayoutConfig.TileSize / 2f);
Key Patterns
Creating New Managers
Follow singleton pattern:
public class NewManager : MonoBehaviour
{
public static NewManager Instance { get; private set; }
void Awake()
{
if (Instance != null) { Destroy(gameObject); return; }
Instance = this;
}
}
Creating New Data Types
For immutable data in Core/Data/:
namespace ZeroDayAttack.Core.Data
{
[System.Serializable]
public class NewData
{
public string Id;
// Serialized fields...
}
}
Creating New View Components
For visual components in View/:
namespace ZeroDayAttack.View
{
public class NewView : MonoBehaviour
{
[SerializeField] private SpriteRenderer spriteRenderer;
// View logic...
}
}
Design Rationale
Key architectural decisions and their reasoning:
| Decision |
Why |
| TileManager not BoardManager |
Avoids confusion with Board SDK (BoardInput, BoardContact) |
| Separate Tile/Token managers |
Different behaviors: tiles fixed, tokens move with players |
| InputManager singleton |
Centralizes SDK, enables mocking, single coordinate conversion |
| ScriptableObject databases |
Inspector-editable, survives refactoring, testable via Resources.Load |
| Board SDK isolation |
Only InputManager imports SDK, enables testing without hardware |
| Event-based communication |
Decouples logic from presentation, multiple listeners |
For full rationale with examples, see design-decisions.md in references.
Reference Files
This skill's references/ folder contains:
| File |
Contains |
Read When |
layer-model.md |
The 6 layers: Data, State, Logic, View, Input, Config |
Understanding layer boundaries |
data-flow.md |
State ownership diagram, event patterns |
Implementing state changes |
class-responsibilities.md |
GameManager, TileManager, TokenManager, InputManager |
Adding features to existing classes |
scene-hierarchy.md |
GameplayScene structure, GameObject organization |
Modifying scene or adding objects |
design-decisions.md |
Why singletons, naming conventions, SDK isolation |
Making architectural decisions |
Key Source Files
When modifying architecture, review:
| File |
Purpose |
LayoutConfig.cs |
All layout constants |
GameManager.cs |
Game orchestration singleton |
TileManager.cs |
Tile spawning, grid conversion |
InputManager.cs |
Board SDK wrapper |
1---2name: project-architecture3description: This skill should be used when the user asks about "namespaces", "singleton", "TileManager", "GameManager", "TokenManager", "InputManager", "data flow", "class responsibilities", "layers", "folder structure", "code organization", "design patterns", "ScriptableObject", "databases", or discusses Zero-Day Attack codebase architecture and patterns.4---56# Zero-Day Attack Project Architecture78Expert knowledge of the Zero-Day Attack Unity codebase structure, design patterns, and architectural decisions.910## Design Principles1112### 1. Separation of Concerns1314The codebase organizes into distinct layers:1516| Layer | Location | Purpose |17| ---------- | --------------------- | -------------------------------------------- |18| **Data** | `Core/Data/` | Immutable data structures, ScriptableObjects |19| **State** | `Core/State/` | Mutable runtime game state |20| **Logic** | `Core/GameManager.cs` | Game rules, orchestration |21| **View** | `View/` | Visual representation, Unity components |22| **Input** | `Input/` | Board SDK abstraction |23| **Config** | `Config/` | Static layout constants |2425**CRITICAL - State Ownership:**2627| Component | Owns | Does NOT Own |28| -------------- | --------------------------------- | ----------------------------- |29| `GameState` | Token positions, game phase, turn | Visual representations |30| `TokenManager` | TokenView instances, visuals | Token positions in game state |31| `GameManager` | Game rules, state transitions | View updates |3233**Anti-pattern:** View layer (TokenManager) directly updating GameState or making game logic decisions. Always route state changes through GameManager.3435### 2. Board SDK Isolation3637Only `InputManager.cs` imports `Board.Input` namespace. This:3839- Prevents SDK types leaking throughout codebase40- Enables testing without hardware41- Centralizes coordinate conversion4243### 3. Singleton Managers4445Core systems use singleton pattern with `Instance` property:4647```csharp48GameManager.Instance // Game state and logic49TileManager.Instance // Tile spawning, positioning50TokenManager.Instance // Token spawning, input handling51InputManager.Instance // Board SDK event broadcasting52```5354### 4. ScriptableObject Databases5556Game data stored in ScriptableObjects:5758- `TileDatabase` - 25 tile definitions with sprites and paths59- `TokenDatabase` - 6 token definitions with sprites and glyph IDs6061## Namespace Organization6263| Namespace | Purpose |64| --------------------------- | ---------------------------------- |65| `ZeroDayAttack.Config` | Layout constants (`LayoutConfig`) |66| `ZeroDayAttack.Core` | Game orchestration (`GameManager`) |67| `ZeroDayAttack.Core.Data` | Data structures, enums, databases |68| `ZeroDayAttack.Core.State` | Runtime state classes |69| `ZeroDayAttack.View` | Visual components, managers |70| `ZeroDayAttack.Input` | Board SDK wrapper |71| `ZeroDayAttack.Diagnostics` | Debug utilities |72| `ZeroDayAttack.Editor` | Editor-only tools |7374### Namespace Rules7576When creating new scripts:7778- Place in appropriate namespace based on responsibility79- Use full namespace declaration: `namespace ZeroDayAttack.View { }`80- Editor scripts: `ZeroDayAttack.Editor`81- Test scripts: Match the namespace being tested8283## Folder Structure8485```text86Assets/Scripts/87├── Config/88│ └── LayoutConfig.cs # Static layout constants89│90├── Core/91│ ├── GameManager.cs # Game orchestrator singleton92│ ├── Data/ # Immutable data structures93│ │ ├── Enums.cs # EdgeNode, PathColor, Player, etc.94│ │ ├── PathSegment.cs # Path connection between nodes95│ │ ├── TileData.cs # Tile definition96│ │ ├── TileDatabase.cs # ScriptableObject: all tiles97│ │ ├── TokenData.cs # Token definition98│ │ └── TokenDatabase.cs # ScriptableObject: all tokens99│ └── State/ # Mutable runtime state100│ ├── BoardState.cs # Grid, reserves, deck101│ ├── GameState.cs # Phase, current player102│ └── TokenState.cs # Token position, ownership103│104├── View/ # Visual components105│ ├── TileManager.cs # Singleton: tile spawning106│ ├── TileView.cs # Individual tile visual107│ ├── TokenManager.cs # Singleton: token spawning108│ ├── TokenView.cs # Individual token visual109│ ├── BackgroundRenderer.cs # Board background110│ ├── CameraController.cs # Camera setup111│ └── GridOverlayRenderer.cs # Grid lines with glow112│113├── Input/114│ └── InputManager.cs # Board SDK wrapper (ONLY Board.Input)115│116├── Diagnostics/117│ └── SceneDiagnostic.cs # Runtime debug118│119└── Editor/120 ├── TileParser.cs # Menu: ZeroDayAttack > Parse Tiles121 └── TokenParser.cs # Menu: ZeroDayAttack > Parse Tokens122```123124## Class Responsibilities125126### Core Layer127128| Class | Responsibility |129| ------------- | --------------------------------------------------------------------- |130| `GameManager` | Initialize game, manage phases, orchestrate state. No direct visuals. |131| `GameState` | Hold `BoardState`, `TokenState[]`, current player, phase, actions |132| `BoardState` | 5×5 grid (`TileData[,]`), reserves, deck, discard |133| `TokenState` | Token identity, position (tile, node), physical tracking |134135### Data Layer136137| Class | Responsibility |138| --------------- | ---------------------------------------------------------- |139| `TileData` | Define tile: ID, sprite, segments, rotation, grid position |140| `TokenData` | Define token: ID, sprite, owner, type, glyph ID |141| `PathSegment` | Connect two `EdgeNode` values with `PathColor` |142| `TileDatabase` | ScriptableObject with `List<TileData>` |143| `TokenDatabase` | ScriptableObject with 6 token slots |144145### View Layer146147| Class | Responsibility |148| --------------------- | ---------------------------------------------------------- |149| `TileManager` | Spawn tiles, grid-to-world conversion, hold `TileDatabase` |150| `TokenManager` | Spawn tokens, handle glyph events, snap to nodes |151| `TileView` | MonoBehaviour on tile GameObjects, manage sprite |152| `TokenView` | MonoBehaviour on token GameObjects, manage position |153| `BackgroundRenderer` | Render board background |154| `GridOverlayRenderer` | Draw 5×5 grid with glow effect |155| `CameraController` | Configure orthographic camera |156157### Input Layer158159| Class | Responsibility |160| -------------- | ----------------------------------------------------- |161| `InputManager` | Poll `BoardInput`, fire events, coordinate conversion |162163## Data Flow164165```text166Board Hardware (touch/glyph)167 │168 ▼169 InputManager ← Only Board.Input import170 │171 ┌────┴────┐172 ▼ ▼173TokenManager (Future: Tile touch)174 │175 ▼176GameManager ← Game logic decisions177 │178┌───┴───┐179▼ ▼180GameState TileManager181BoardState (spawn tiles)182TokenState183```184185### Event-Driven State Updates186187GameManager should expose events for state transitions:188189```csharp190// GameManager events191public event Action OnSetupComplete;192public event Action<TokenState> OnTokenPlaced;193public event Action<TokenState> OnTokenMoved;194public event Action<Player> OnTurnChanged;195```196197**Flow Example (Token Placement):**1981991. `InputManager` detects glyph, fires `OnContactBegan`2002. `TokenManager` receives event, calls `GameManager.PlaceToken()`2013. `GameManager` validates placement, updates `GameState`2024. `GameManager` fires `OnTokenPlaced` event2035. `TokenManager` (subscribed) updates visual position204205## Scene Hierarchy206207```text208GameplayScene209├── MainCamera [CameraController]210├── GlobalLight2D211├── GameManager [GameManager]212├── TileManager [TileManager]213├── TokenManager [TokenManager]214├── InputManager [InputManager]215├── BackgroundRenderer [BackgroundRenderer]216├── GridOverlayRenderer [GridOverlayRenderer]217├── Tiles (spawned at runtime)218└── Tokens (spawned at runtime)219```220221## Coordinate Systems222223### Grid Coordinates224225- Origin: (0, 0) = bottom-left of 5×5 grid226- Range: (0, 0) to (4, 4)227- Center tile: (2, 2)228229### World Coordinates230231- Origin: (0, 0) = screen center = grid center232- Grid spans: -5.0 to +5.0 in X and Y233- Tile size: 2.0 world units234235### Conversion236237```csharp238// Grid to World (via LayoutConfig)239float x = LayoutConfig.GridLeft + (gridX * LayoutConfig.TileSize) + (LayoutConfig.TileSize / 2f);240float y = LayoutConfig.GridBottom + (gridY * LayoutConfig.TileSize) + (LayoutConfig.TileSize / 2f);241```242243## Key Patterns244245### Creating New Managers246247Follow singleton pattern:248249```csharp250public class NewManager : MonoBehaviour251{252 public static NewManager Instance { get; private set; }253254 void Awake()255 {256 if (Instance != null) { Destroy(gameObject); return; }257 Instance = this;258 }259}260```261262### Creating New Data Types263264For immutable data in `Core/Data/`:265266```csharp267namespace ZeroDayAttack.Core.Data268{269 [System.Serializable]270 public class NewData271 {272 public string Id;273 // Serialized fields...274 }275}276```277278### Creating New View Components279280For visual components in `View/`:281282```csharp283namespace ZeroDayAttack.View284{285 public class NewView : MonoBehaviour286 {287 [SerializeField] private SpriteRenderer spriteRenderer;288 // View logic...289 }290}291```292293## Design Rationale294295Key architectural decisions and their reasoning:296297| Decision | Why |298| -------------------------------- | --------------------------------------------------------------------- |299| **TileManager not BoardManager** | Avoids confusion with Board SDK (`BoardInput`, `BoardContact`) |300| **Separate Tile/Token managers** | Different behaviors: tiles fixed, tokens move with players |301| **InputManager singleton** | Centralizes SDK, enables mocking, single coordinate conversion |302| **ScriptableObject databases** | Inspector-editable, survives refactoring, testable via Resources.Load |303| **Board SDK isolation** | Only InputManager imports SDK, enables testing without hardware |304| **Event-based communication** | Decouples logic from presentation, multiple listeners |305306For full rationale with examples, see `design-decisions.md` in references.307308## Reference Files309310This skill's `references/` folder contains:311312| File | Contains | Read When |313| --------------------------- | ----------------------------------------------------- | ----------------------------------- |314| `layer-model.md` | The 6 layers: Data, State, Logic, View, Input, Config | Understanding layer boundaries |315| `data-flow.md` | State ownership diagram, event patterns | Implementing state changes |316| `class-responsibilities.md` | GameManager, TileManager, TokenManager, InputManager | Adding features to existing classes |317| `scene-hierarchy.md` | GameplayScene structure, GameObject organization | Modifying scene or adding objects |318| `design-decisions.md` | Why singletons, naming conventions, SDK isolation | Making architectural decisions |319320## Key Source Files321322When modifying architecture, review:323324| File | Purpose |325| ----------------- | ------------------------------ |326| `LayoutConfig.cs` | All layout constants |327| `GameManager.cs` | Game orchestration singleton |328| `TileManager.cs` | Tile spawning, grid conversion |329| `InputManager.cs` | Board SDK wrapper |