این مطلب بخشی از تمرین های درس معماری نرمافزار دانشگاه شهید بهشتی است
This report presents the software architecture of an online, server‑authoritative mobile game built with a Unity client and a Nakama backend (Go runtime). The two repositories—Unity application and Nakama server module—compose a cohesive system that provides deterministic turn‑based gameplay, matchmaking with a batched cadence, authoritative move validation, per‑turn deadlines, personalized state dissemination, and resilient rejoin behavior. The Architecture is documented using multiple ISO/IEC/IEEE‑42010‑aligned viewpoints (context, logical, process/runtime, information, and deployment), provide high‑level sequence and component diagrams, and outline a final‑form production architecture. I also survey alternative architectural stacks, summarize trade‑offs, and compare approaches across learning curve, scalability, control, and other criteria.
This project implements a competitive, turn-based version of Tic-Tac-Toe for mobile. Two players share a 3×3 grid; X acts first and O responds, with turns alternating until one player forms a straight line of three marks along a row, column, or diagonal. If all cells are filled without such a line the result is a draw. The gameplay is intentionally strict: the server validates every move, enforces a 10-second per-turn deadline, and declares the opponent the winner on timeout or voluntary departure. Clients never “decide” outcomes; they render the authoritative state they receive and submit only move intents.
The proposed architecture is a deliberately thin Unity client coupled to a Nakama backend that hosts the authoritative game logic in a Go runtime module. The client authenticates with Nakama over HTTP/gRPC and participates in matchmaking over a pool that is batched at 10-second intervals. Once matched, play proceeds on a persistent WebSocket channel where the server sends personalized snapshots including the recipient’s seat (seat_you), the next mover, the current board, an optional winning line, and the absolute deadline tick for the active turn. The client derives “your turn” purely from that snapshot and transmits moves as compact JSON messages. Robustness is ensured by a rejoin mechanism: if a device reconnects during an ongoing match, the client re-enters the match and resumes from the next snapshot without divergence.
Content is delivered via Unity Addressables to separate code from art and layout. Core UI remains local for instant startup, while the gameplay prefab (the board and its cells) is hosted remotely behind a static endpoint. On launch, the client initializes Addressables, checks for catalog updates, and loads the latest board prefab before play. This arrangement supports rapid visual iteration and light gameplay UI changes without republishing the application.
The architecture is documented and evaluated through several complementary viewpoints. The context view positions the Unity app, Nakama services, the matchmaker, and the content CDN, clarifying external dependencies and trust boundaries. The logical view decomposes the client into UI, networking, and gameplay orchestration components and the server into the matchmaker hook and the match handler, establishing responsibilities and interfaces. The process/runtime view traces the match lifecycle—pooling, seating, move validation, deadlines, and termination—at a fixed server tick rate that decouples transport jitter from rules enforcement. The information view specifies the minimal protocol—opcodes, payloads, and the semantics of authoritative snapshots—so that both correctness and client simplicity are maintained. The deployment view maps these concerns onto a concrete runtime: an Android build (IL2CPP, ARM64), a Nakama container with the Go plugin, and a static host for Addressables, with an optional reverse proxy and observability stack for production.
Across these views the design goals remain consistent: fairness through server authority, determinism through single-source-of-truth snapshots, operability through containerized deployment and content hot-updates, and resilience through explicit rejoin semantics and time-bounded turns.

Key external actors are the matchmaker and a static content CDN for Addressables. The database is not used during turn resolution (in‑memory match state) but can be used for summaries and live‑ops in future work.

Responsibilities:
- Client: subscribe on the live socket, render authoritative snapshots, throttle input to your turn, manage rejoin, and fetch the remote board prefab.
- Server: assign seats deterministically, validate moves, maintain per‑turn deadlines, and unicast personalized snapshots (including seat_you).

The handler runs at 5 Hz, advancing deadline_tick and enforcing a 10‑second per‑turn timeout. Personalized snapshots ensure both clients know their role and the current turn immediately.
Inbound: opMove with { "index": 0..8 }.
Outbound: opStateopGameOver with:

The client treats every snapshot as authoritative; UI timers are derived from configuration (10 s) and can be made precise by including a server tick in future work.

One command brings up the backend: docker compose up --build (multi‑stage build compiles and mounts the Go plugin). The client points to the server’s host/port and fetches remote gameplay content via Addressables.

seat_you)


This section sketches an end‑state production architecture that extends the current minimal system with social, economy, competition, and live‑ops features—while preserving server authority.

Key properties: authoritative writes via RPC/hooks, persistent storage for identity/economy, ranked leaderboards with seasonal resets, friends/clans for social retention, and operational endpoints and jobs for live‑ops. Addressables continues to deliver remote content updates.
- Description. Client uses Photon for realtime rooms and PlayFab for auth, data, and economy. High velocity with managed services; less control over server‑side game logic unless using Photon Server SDK separately.

- Description. Suitable for casual/async play. Realtime DB/Firestore events and Cloud Functions implement logic; not ideal for authoritative low‑latency realtime, but simple and scalable for turn‑based without sockets.

- Description. Game logic in Node.js rooms; good developer experience, full control, self‑hosted on Docker/K8s. Requires building social/economy or pairing with external services.


The Unity + Nakama architecture achieves a principled split of responsibilities: a thin, reactive client renders server‑authoritative state, while the backend ensures correctness, fairness, and resilience. The same extension points (RPCs, hooks, jobs, custom HTTP) can scale this minimal prototype into a full game backend with leaderboards, shops, storage‑backed identity and inventory, friends/clans, and parties—all while retaining deployer control and open‑source transparency.
Heroic Labs, “Nakama: Open‑Source Game Server”
Unity Technologies, “Addressables,” Manual
Photon Engine Multiplayer Services
Microsoft Azure Playfab Multiplayer Services
Colyseus Multiplayer Framework
Appendix A — Repositories
https://github.com/KhodadadMahdavi/SAC_Game
https://github.com/KhodadadMahdavi/SAC_NakamaServer
Appendix B — Video Demonstration of the Final Game