With my plans on changing the combat system, a big refactoring effort on my code is needed.
I received good feedback on my article about a loosely-coupled system for code in games. So I think I should apply the principles back to my code in Tactics Ensemble.
I should start with revisiting my unit low-level classes.
My previous code was a thin layer behind Unity’s Animation class. Users of this class had to compute things by themselves, specifying blend time between animations, needing to check for animation playback positions themselves, etc. I need to change this so it would be a fire-and-forget scenario. Just send requests to do a certain animation, and let the UnitAnimation class figure out the little details by itself.
Some simple class should facilitate what default animations should be used for idle, what default hurt animation should be used when getting damaged, what animation should be played when unit is selected, and whatnot.
This is a good time to revisit the arguments between Character Controller and Rigidbody. Which one should I use now? I should also redo pathfinding, obstacle avoidance, and pushing other units, in a cleaner way now. I should also consider how this class is used by the human player input and by the AI system, how different should handling those two users be.
This is the class that was missing from my systems. A separate class should handle the little details of turning on or off melee collisions, and launching of projectiles at the right time.
This is also something I need to add. A class that handles GUI for the unit, meaning what effect should happen when the unit is highlighted, when the mouse is hovered over it, when it is selected, etc.
The healthbar and any other icons floating above this unit should also be handled by this class.
Should also communicate with the GUI HUD to display this unit’s actions, portrait, name, etc. on the HUD.
Something I could add later on. It would basically take note of all incoming function calls to all low-level classes, record at what time they were called. When watching a replay, we simply review the list made, and call the appropriate functions at the proper time. This only handles the replay for one unit, so we have one UnitReplay for each unit in the battle.
Unit Facade Class
I should make the Unit class refer to the low-level classes via interfaces only. I’d need to clean this up as well to accommodate the new combat system.
I think I also need to question my system on Actions and Effects.
It would be beneficial if I convert my Effects system to just use behaviour trees instead. It would make editing more consistent, and add flexibility to attacks; you could add conditional effects easily (e.g. if my health > enemy health, deal 2x damage).
Actions (i.e. attacks) would get a revamp, to accommodate the new combat system to be experimented on. I also need to consider if it can be improved to integrate with the AI system better.
Local Player Singletons
This is the set of singletons used to facilitate player input from mouse and keyboard.
They manage selecting a friendly unit on behalf of the player, relaying orders to it, facilitating when the game is asking the player for a destination/target to click on, etc. Basically it handles player input from the local machine (as opposed to input from across the network in a multiplayer game).
I think I should separate this to a low level that handles mouse and keyboard directly, and a high level that sits in problem domain. With that, I should be able to add touch-screen controls later without messing the existing code.
The class that handles which unit is currently selected. In the normal flow of how a player plays the game, this is where it all starts.
Since it manages which unit is selected, this dictates which unit will be given orders by the player.
This is one of the things that probably needs decoupling, with a UnitSelectorMouseKeyboard that listens for left-clicks and keypresses, and a high-level UnitSelector that facilitates OnSelected events, tells which unit is currently selected to whoever asked it, and whatnot.
Accepting input from GUI buttons should also be handled by a separate, low-level class. BattleNGUI. This would be the one directly handling NGUI.
This low-level class will listen in on unit selection events, so it can make sure the currently selected unit’s action buttons, portrait, name, etc. get displayed (in NGUI). Each action button would somehow be able to fire off requests to activate that action of that unit.
A BattleHotkey class or something would essentially do the same of allowing sending of requests to do an action of the selected unit, but now by keyboard hotkey presses instead.
Camera movement would normally be independent from everything else, being controlled by the player only.
However, there are times when the camera would be controlled by the game.
When an enemy unit is moving on its turn, the camera should center to it (which I haven’t implemented).
And some actions or events may call for showing cinematic shots of characters.
Effects like camera shake would also be handled by this system.
Decoupling is also in order here. A CameraControlMouseKeyboard would listen for keyboard and mouse input while CameraControl provides the actual moving, rotating, zooming. There would be a CameraControlTouch for touchscreen devices.
Fairly rudimentary right now, and I don’t think I’ll be changing this soon. When the time comes, I may experiment on giving AI players a central behaviour tree to use.
Right now, each AI unit thinks for itself. But coordination may be better if I give the AI player its own behaviour tree. It would look at the battlefield map from a tactician’s point of view, then it would tell each unit what role they should be in (go to the defensive, attack from this side, scout here, etc.).
Battle Manager Singleton
This singleton acts as umpire, deciding when the battle has ended, who won and who lost. It manages a list of all players in the game, so it can decide whose turn is next. Very simple piece of code, and I probably don’t need to do anything here.
If I knew how to make UML diagrams I probably would make one now.