Why this page exists
Codebase disorientation is one of the most common sources of architecture violations. A developer who doesn’t know whereISetValidator lives might accidentally implement validation logic in a MonoBehaviour. This tour prevents that by giving you a reliable mental map before you write a single line.
Key responsibilities
This page owns three navigation outcomes for every contributor:Top-level folder structure
Everything production-relevant lives underAssets/_Project/. Third-party libraries, tests, and editor tools each have their own top-level sibling folders to keep them cleanly separated from game code.
The entry-point scene
Assets/_Project/Scenes/Bootstrap.unity is the only scene listed in Build Settings. It performs three jobs when it runs:
- Instantiates the VContainer
LifetimeScopethat wires all dependency injection bindings. - Loads persistent manager objects (audio, platform services, local save).
- Transitions additively into
MainMenu.unity.
GameBoard, PostMatch) is loaded additively from within the game flow — never directly. Always use Bootstrap as your editor Play entry point.
Assembly definition map
The project uses Unity Assembly Definition files (.asmdef) to enforce layer boundaries at compile time. If you reference a type from the wrong assembly, the project will not compile — this is intentional.
The dependency graph looks like this:
SET.Presentation binds to SET.Infrastructure only at runtime through VContainer’s DI container inside the Bootstrap scene. There is no compile-time reference — Presentation simply knows the interfaces defined in Application, and VContainer supplies the concrete implementations at startup.
What lives in each layer
Domain layer — _Project/Domain/
The innermost layer. Contains everything needed to represent and validate a game of SET, with zero external dependencies.
Match is the aggregate root — code outside the Domain layer interacts with game state exclusively through Match’s public API, never by reaching into its child entities directly.
Application layer — _Project/Application/
Orchestration logic. Depends only on SET.Domain.
GameSession is the central state machine for a match. It receives IGameCommand objects, coordinates Domain entities, and pushes state changes out as R3 observables. It has no knowledge of Unity, Nakama, or the UI.
Infrastructure layer — _Project/Infrastructure/
Implements the interfaces defined in Application using real external SDKs.
All Nakama types (e.g.,
IMatch, IApiUser) are converted into plain domain DTOs before they cross the Infrastructure boundary into Application or Domain.
Presentation layer — _Project/Presentation/
Everything Unity-dependent. Depends on Domain and Application, never Infrastructure.
MonoBehaviours in this layer are thin views. They bind UI elements to ViewModel properties and forward user input. They never contain game logic.
Config files
Runtime configuration lives inAssets/_Project/Data/ as plain JSON files:
These files are loaded at runtime via
Resources.Load or Addressables; parsing logic lives in Infrastructure/Serialization/.
The golden rule
Dependencies always point inward. Outer layers know about inner layers. Inner layers know nothing about outer layers.If you’re in the Domain layer and you’re about to add
using SET.Application; — stop. That reference goes the wrong direction. If you’re in Presentation and you’re about to add using SET.Infrastructure; — stop. Use the interface from Application instead, and let VContainer supply the implementation.
Implementation checklist
Use this checklist when adding a new file to confirm it belongs in the right place:- New domain type? File goes in
Assets/_Project/Domain/(entity, value object, enum, or interface) with no external references - New application interface? File goes in
Assets/_Project/Application/Services/— Infrastructure implements it, Presentation consumes it - New Infrastructure class? File goes in
Assets/_Project/Infrastructure/<Subsystem>/— implement the Application interface, register in Bootstrap - New MonoBehaviour view? File goes in
Assets/_Project/Presentation/Views/with a paired ViewModel inPresentation/ViewModels/ - New scene? File goes in
Assets/_Project/Scenes/— never inside a layer subfolder - New test? EditMode tests for Domain/Application in
Assets/_Tests/EditMode/; PlayMode integration tests inAssets/_Tests/PlayMode/ - New config? JSON config files go in
Assets/_Project/Data/; parsed by Infrastructure serialization code
Common mistakes
Related pages
Prerequisites
Software, accounts, and setup steps before you open the project.
First Tasks
Where to start contributing — Domain-layer work that needs no Unity runtime.
Architecture Layers
Deep dive into what each layer owns, forbids, and how they communicate.
Assembly Definitions
How
.asmdef files enforce compile-time dependency rules.