Architecture & delivery case · Unity 2022 LTS

2D Asteroids Survival

A feature-complete survival game built around custom fixed-step simulation, validated JSON configuration, explicit dependency boundaries, transactional pooled lifecycles, and guarded desktop/mobile delivery.

Dependency map

Gameplay rules, engine adapters, and presentation have explicit boundaries.

Four project assemblies separate contracts and physics primitives from JSON/input/platform adapters, gameplay orchestration, and UI. Domain-focused Zenject installers compose them without runtime service lookup.

Core
Config DTOs · physics primitives · contracts
Infrastructure
JSON · input · scenes · SDK adapters
Gameplay
Fixed loop · combat · pools
UI
ViewModels · Unity views

Key engineering decisions

Order, ownership, and platform boundaries stay visible in code.

One named fixed-step pipeline

GameplayFixedLoop is the only IFixedTickable entry point. It runs player state, movement, integration, projectiles, world bounds, collisions, and presentation synchronization in an explicit order.

Custom physics and toroidal space

Plain C# bodies, integrators, circle and segment queries, elastic response, and ToroidalWorld2D own gameplay simulation without Physics2D or dynamic Rigidbody2D behavior.

Validated data boundaries

Player, enemy, and world balance load from JSON. Validation rejects invalid values and missing, unknown, null, duplicate, or incorrectly cased enemy keys before gameplay scenes open.

Transactional pooled lifecycle

ObjectPool<T> tracks created instances, provides FIFO reuse, and rejects duplicate returns. EnemyPool centralizes rent, initialization, registration, activation, teardown, and rollback while concrete pools keep type-specific work.

One input snapshot, two strategies

Desktop and mobile strategies use Unity's classic Input API behind one contract. PlayerInputStateProvider samples the selected strategy once per rendered frame for movement and both weapons.

Guarded platform integration

UniTask navigation prevents duplicate transitions and restores UI after failure. Firebase Analytics and AdMob stay behind adapters; missing ad configuration selects a disabled service instead of breaking bootstrap.

Runtime and maintainability

Hot paths and failure paths are explicit.

Gameplay avoids scene-wide lookup, repeated component discovery, and temporary hot-loop collections. Cached references, registries, and owned lifecycle operations keep cost and cleanup predictable.

Centralized collision and lookup

Enemy and projectile registries support custom circle and segment queries; HashSet membership and direct entity mappings prevent duplicate registration and concrete-pool scans.

Failure-safe spawn lifecycle

Enemy and projectile spawn paths reverse completed registrations and return rented views if a later stage fails. SignalBus and event subscriptions have deterministic teardown.

Authored data in the right format

JSON owns extensible runtime balance; ScriptableObjects remain where Unity asset references are appropriate. Unity-facing dependencies are serialized, validated, and cached before gameplay.

Review and delivery

Feature-complete code with playable desktop and mobile builds.

The public repository contains the complete Unity project, configuration, setup notes, and architecture review map. The 21-point architecture review is closed; final Android device and release-build validation remains a separate gate.

Gameplay scope

Ship acceleration and inertia, toroidal movement, asteroids and fragments, pursuing UFOs, bullets, multi-target laser, health, invulnerability, scoring, HUD, game over, restart, and menu flow

Technology

Unity 2022.3.9f1, C#, custom fixed-step 2D physics, classic Unity Input, Zenject, SignalBus, UniTask, Newtonsoft.Json, UGUI, Firebase Analytics, Google Mobile Ads, Windows, Android

Architecture, lifecycle & validation case

Last Seed Survivor

Continue with engine-free domain state, explicit frame orchestration, transactional pooled lifecycles, failure-safe rewards, project-wide tests, and deterministic balance tooling.

Open Last Seed case →