Overview
Three heroes against a scourge of monsters. Block in real time, upgrade and evolve between fights, and push through the stages one horde at a time.
Everything · design, code, tools, UI
My largest personal project, and the one I would point at first. Built solo since February 2025 and now live on Google Play.
The spine of it is one abstraction. Heroes and enemies both derive from the same abstract Fightable, so the turn system, status calculation, actions and animation resolve through one polymorphic path instead of two parallel ones. Systems talk to each other through ScriptableObject events rather than direct references, which is what allowed hordes, notifications, consumables and a summary screen to be added later without reopening combat.
Combat is turn-based but not passive. A block action lets you cut incoming damage if you read the attack in time, and the enemy AI runs on data-driven profiles and attack patterns written to be legible in advance, so blocking is a decision rather than a guess.
It is the project where I have built the entire stack myself: stage progression and meta-game, a store with real IAP, a reward roulette, Firebase and Google Play Games login, a CrazyGames SDK integration with a WebGL build, two separate tutorials covering the first battle and the meta-game, and the audio and feedback layer over all of it.
- Three heroes, 15+ monsters, one final boss
- 42 stages across three biomes
- 30 systems on SOLID and shared abstractions
- Built solo and shipped, live on Google Play

My contributions
Character architecture
- Built Fightable as an abstract base that both heroes and monsters derive from, so the turn system holds one type and never asks what it is holding. Adding a character class means implementing the abstraction, not extending a switch, which is the Liskov substitution principle carrying the whole battle loop.
- Composed each character from focused components rather than one inheriting class: status, action handler, state handler, animation handler, buff ability and body parts are separate types the base holds references to. Composition over inheritance is what allowed monsters to reuse hero behaviour without inheriting hero data.
- Wired systems together through ScriptableObject events rather than direct references. Nothing in combat holds a pointer to the UI, so hordes, notifications, consumables and a summary screen were all added later without reopening a single combat class.
- Built persistent hero inventory, character unlocks and skins bound to evolution tiers.
Status and abilities
- Built AccumulativeStatusModifier as an abstract base with stacking, cleansing and turn-triggered effects, and derived poison, bleeding, confusion, shield and the dominance and leader auras from it. A new effect is a subclass with its own MaxStacks and trigger, and no existing effect is touched, which is the open/closed principle in its most literal form.
- Extended that base again into a temporary variant for effects that expire, so duration is inherited behaviour rather than a flag every effect has to remember to honour.
- Implemented the block ability with a cooldown, a turn-scoped stance, and listeners registered in Awake and removed in OnDestroy so nothing leaks between battles.
- Built weakness multipliers per attack type and the effects screen listing what is active and how many turns remain, since a turn-based fight is only readable if its state is visible.
Battle system
- Built turn order, spawning, stage entrance and exit animations, fades and cutouts as separate concerns over a single battle controller, keeping each class to one reason to change.
- Implemented the block action as the player's defensive move: read the incoming attack, commit in time, and cut the damage. It replaced an earlier quick-time-event prototype, and the input, stance and damage-multiplier handling that survived it are now the block ability itself.
- Supported multiple hordes per stage with the visualisation, spawn notifications and return-to-world flow around them.
- Built a pre-fight summary screen generated from stage data, showing unlocked characters against the enemy roster.
Heroes, enemies and AI
- Built three heroes individually (pirate, mage, gunner), each with a main attack, a special, projectiles and buff abilities, all resolving through the shared Fightable contract.
- Built enemy AI on data-driven profiles: a ScriptableObject per profile, a collection binding profiles to monsters, and attack patterns authored as assets. Tuning an enemy is editing an asset, and a new monster needs no new AI code.
- Wrote the attack patterns to be legible a turn ahead, which is what makes blocking a decision rather than a guess.
- Created 15+ monsters and the final boss fight on that same architecture.
Reusable foundations
- Wrote a generic PoolSystem<T> constrained to UnityEngine.Object, handling both MonoBehaviour and GameObject instances behind one API, so every pooled system in the game shares one implementation instead of copying it.
- Built generic Singleton and PersistentSingleton bases for the few systems that genuinely need global access, rather than scattering static state.
- Built camera control on an abstract input strategy, so touch and mouse are interchangeable implementations behind the same controller.
Meta-game and economy
- Built the stage system with unlocking, compass focus and reveal animations.
- Built resource inventory and consumables with their own input flow, purchase-when-missing handling and turn accounting.
- Built a store with bundles and real IAP, and replaced an earlier level system with coin-based upgrades and evolutions.
- Built a reward roulette with ad and gem re-spins, and the distribution logic behind it.
Tutorials
- Built two separate tutorials: one covering the first battle, and one covering the meta-game and character upgrades.
- Put each on its own layer with a guide hand, and added guards across unrelated features so new work could not break either path.
Platform, SDKs and feel
- Integrated Firebase and Google Play Games login with the loading screen and save-conflict handling around it.
- Integrated the CrazyGames SDK with account management and ads across both platforms, and shipped the WebGL build.
- Handled notch safe areas, an FPS display setting, and project and sprite level optimisation passes.
- Built the audio system with looped world-to-battle transitions, plus damage blink, floating damage text and gradient hit feedback.
Gallery
Project details
- Studio
- Solo
- Genre
- Turn-Based RPG
- Engine
- Unity
- Released
- Out now
- Platforms
- Web, Android
- Stack
- Unity · C# · Turn-Based · Systems Architecture · Enemy AI · Meta Systems · Monetization · WebGL





