AgentSkillsCN

project-architecture

当用户询问“命名空间”、“单例”、“TileManager”、“GameManager”、“TokenManager”、“InputManager”、“数据流”、“类职责”、“层”、“文件夹结构”、“代码组织”、“设计模式”、“ScriptableObject”、“数据库”或讨论Zero-Day Attack代码库架构和模式时,应使用此技能。

SKILL.md
--- frontmatter
name: project-architecture
description: 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.
version: 0.3.0

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:

LayerLocationPurpose
DataCore/Data/Immutable data structures, ScriptableObjects
StateCore/State/Mutable runtime game state
LogicCore/GameManager.csGame rules, orchestration
ViewView/Visual representation, Unity components
InputInput/Board SDK abstraction
ConfigConfig/Static layout constants

CRITICAL - State Ownership:

ComponentOwnsDoes NOT Own
GameStateToken positions, game phase, turnVisual representations
TokenManagerTokenView instances, visualsToken positions in game state
GameManagerGame rules, state transitionsView 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:

csharp
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

NamespacePurpose
ZeroDayAttack.ConfigLayout constants (LayoutConfig)
ZeroDayAttack.CoreGame orchestration (GameManager)
ZeroDayAttack.Core.DataData structures, enums, databases
ZeroDayAttack.Core.StateRuntime state classes
ZeroDayAttack.ViewVisual components, managers
ZeroDayAttack.InputBoard SDK wrapper
ZeroDayAttack.DiagnosticsDebug utilities
ZeroDayAttack.EditorEditor-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

text
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

ClassResponsibility
GameManagerInitialize game, manage phases, orchestrate state. No direct visuals.
GameStateHold BoardState, TokenState[], current player, phase, actions
BoardState5×5 grid (TileData[,]), reserves, deck, discard
TokenStateToken identity, position (tile, node), physical tracking

Data Layer

ClassResponsibility
TileDataDefine tile: ID, sprite, segments, rotation, grid position
TokenDataDefine token: ID, sprite, owner, type, glyph ID
PathSegmentConnect two EdgeNode values with PathColor
TileDatabaseScriptableObject with List<TileData>
TokenDatabaseScriptableObject with 6 token slots

View Layer

ClassResponsibility
TileManagerSpawn tiles, grid-to-world conversion, hold TileDatabase
TokenManagerSpawn tokens, handle glyph events, snap to nodes
TileViewMonoBehaviour on tile GameObjects, manage sprite
TokenViewMonoBehaviour on token GameObjects, manage position
BackgroundRendererRender board background
GridOverlayRendererDraw 5×5 grid with glow effect
CameraControllerConfigure orthographic camera

Input Layer

ClassResponsibility
InputManagerPoll BoardInput, fire events, coordinate conversion

Data Flow

text
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:

csharp
// 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):

  1. InputManager detects glyph, fires OnContactBegan
  2. TokenManager receives event, calls GameManager.PlaceToken()
  3. GameManager validates placement, updates GameState
  4. GameManager fires OnTokenPlaced event
  5. TokenManager (subscribed) updates visual position

Scene Hierarchy

text
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

csharp
// 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:

csharp
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/:

csharp
namespace ZeroDayAttack.Core.Data
{
    [System.Serializable]
    public class NewData
    {
        public string Id;
        // Serialized fields...
    }
}

Creating New View Components

For visual components in View/:

csharp
namespace ZeroDayAttack.View
{
    public class NewView : MonoBehaviour
    {
        [SerializeField] private SpriteRenderer spriteRenderer;
        // View logic...
    }
}

Design Rationale

Key architectural decisions and their reasoning:

DecisionWhy
TileManager not BoardManagerAvoids confusion with Board SDK (BoardInput, BoardContact)
Separate Tile/Token managersDifferent behaviors: tiles fixed, tokens move with players
InputManager singletonCentralizes SDK, enables mocking, single coordinate conversion
ScriptableObject databasesInspector-editable, survives refactoring, testable via Resources.Load
Board SDK isolationOnly InputManager imports SDK, enables testing without hardware
Event-based communicationDecouples logic from presentation, multiple listeners

For full rationale with examples, see design-decisions.md in references.

Reference Files

This skill's references/ folder contains:

FileContainsRead When
layer-model.mdThe 6 layers: Data, State, Logic, View, Input, ConfigUnderstanding layer boundaries
data-flow.mdState ownership diagram, event patternsImplementing state changes
class-responsibilities.mdGameManager, TileManager, TokenManager, InputManagerAdding features to existing classes
scene-hierarchy.mdGameplayScene structure, GameObject organizationModifying scene or adding objects
design-decisions.mdWhy singletons, naming conventions, SDK isolationMaking architectural decisions

Key Source Files

When modifying architecture, review:

FilePurpose
LayoutConfig.csAll layout constants
GameManager.csGame orchestration singleton
TileManager.csTile spawning, grid conversion
InputManager.csBoard SDK wrapper