DAREN TRINH
Unity Developer | Gameplay Programming | Technical QA
Android RPG Project
Development Notes
I started this project back in May 2022 and ended development in January 2023, I decided to use this project as a means of learning to develop systems that are more abstract and open for future implementation.
A lot of thought and planning went into the design of the mobile controls, how to integrate a Turn-Based RPG's multitude of choices into a small screen space, and seeing what design choices were made to streamline the genre into shorter battles that still felt engaging.
The biggest hurdle I've had on this project has been creating the core system for the combat in the game. A good chunk of my development spare time went into designing the system that could allow for me to create new enemies and playable units easily without having to spend much time on creating code for new units.
Designing the damage calculation system for battles was a challenge as each Turn-based RPG has their own unique methods of implementing their designed combat system. Fire Emblem: Heroes and Honkai: Star Rail damage calculations was the inspiration when designing a streamlined combat in a mobile playable format.
Notable Features
Some notable features in this project is the Turn-System's design and the Entity code structure. These two features took a lot of refactoring and redesigning as I was constantly looking to find new and better ways to implement them.
BattleManager
The Turn-System was designed with the Finite State Machine computation model in mind. The Turn-System or Battlemanager in this project has pre-defined enums which represent our game states and a currentGameState variable.
The CheckState method on the Battlemanager is subscribed to our EventHandler's OnStateEnd.
The CheckState method will check the value of the currentGameState enum and set it to, and call the necessary methods.
The BattleStart GameState handles spawning Entities and populating a list of UnitsInBattle based on the Speed value ("Spd") in descending order.
The BetweenTurn state checks what the currentGameState enum value is and gets called at the end of any GameState. Below are the following conditions for changing states:
-
If the HasPlayerLost boolean is true, we set the currentGameState to the GameLoss state and invoke the OnStateEnd event.
-
If our HasPlayerWon boolean is true, we set the currentGameState to GameWon and invoke the OnStateEnd event.
-
If neither conditions returns true, we start sorting through the UnitsInBattle list and either got to the PlayerTurn or EnemyTurn state (based on whether the entity is controllable or not).


Entities
Agent and enemy scripts are inherited from the base class Entity Script carries a reference to a ScriptableObject that has unique character data.
Both Enemy and Agent scripts have a override function to the Entity's SetSpawnPoint function that have their own code to set their transform to their respective position.
The Entity script implements an IDamageable Interface that holds functionality for objects to have its HP value adjusted (this is to create damageable objects in combat which may not be Entities but carry damageable traits).
This script is also subscribed to a OnDeathCheck event that occurs between game state transitions. The Entity script will check its current HP and set its mesh renderer to false when its HP is less than or equal to zero.


Testing & Debugging
Throughout development, I evaluated the turn-based combat system to ensure that its gameplay mechanics and underlying systems behaved as intended.
This included examining speed-based turn ordering, verifying that defeated entities could no longer participate in combat, and checking that the BattleManager transitioned correctly between player and enemy turns. I also examined damage calculations, health updates, and victory and defeat conditions to ensure that combat outcomes were processed correctly.
Using Unity's Inspector and Console, I monitored entity attributes, combat states, and execution flow to investigate unexpected behaviour and identify potential issues. This process helped me better understand how individual gameplay systems interact and the importance of validating both expected behaviour and edge cases.