“The secret to getting ahead is getting started.”
― Mark Twain
Having learned a lot about game development and design in the last year, it is time to share that knowledge with the world. Stepping out of the shadows and into the light, I feel I am finally ready to start cataloging my efforts, discoveries, and tips on the internet. This dev blog series will be highlighting my development efforts each week on the current project on which I am working, Operation Phantasm. A game that fuses the unit micro management of StarCraft II, the unit personality of X-Com, and the psychological mechanics of Darkest Dungeon. What does the player do you might ask? The player manipulates the mental states, positions, and actions of five characters through real time micro management, the player’s goal is to escape the nightmare realm with as many characters as possible. For those interested in the lore, the opening statement from the pitch should suffice for now.
“Nightmares, what happens when you can’t wake up? What happens when the creatures that terrorize your mind, are your family friends and loved ones?”
– Tyler Fronczak, Operation Phantasm Creative Lead
The goal of this project is to see what we can come up with between January and May, working off the initial pitch for the game. The four-person team I am working with is made up of fledgling designers eager to test, and improve, our skills by creating a fun and intriguing RTS experience in unity. Throughout the development process some of my experiences, techniques, and trials will be documented in weekly devblogs. Starting with this one.
Week One: Operation Phantasm
My main responsibilities for this project are to create and maintain the combat systems. This entails a lot of behind the scenes work that the player will never see or know about. Things that enable and support the team’s efforts to create interesting enemies, meaningful abilities, and nail-biting combat scenarios. It also means I will be working on a lot of things that prop up the things the player will become intimately familiar with throughout the play experience. Such as health, ammo, and various other stats as well as the results of combat related actions e.g. damaging enemies, ability effects, etc.
Each week the whole team meets and discusses the current state of development, the current feature list, what stays, what goes, and how we should go about getting to the next milestone. The result is a new task list every week. Each member is assigned a series of tasks that when summed up, get us closer to the finish line. Typically, each member will have tasks that relate to a certain type of system in the game. For example, my tasks will generally focus on combat systems. Whereas my team mate Jude will typically focus on player feedback and UI. I say typically because the nature of game development in a small team dictates that we will all inevitably need to wear many different hats.
Week One Tasks
High level gameplay descriptions:
Characters all have health, ammo, aim rating, damage, fear, despair, and delusion stats.
Players and enemies can attack each other and do damage.
There is a projectile and ray cast ability. Each does damage and has a cooldown.
(1) Create a class that contains all the stats that can be displayed to the player through the HUD. These stats include: Health, Ammo, Aim, Damage, Fear, Despair, and Delusion.
(2) Create functions to modify these values, which don't allow a value to exceed a specified max or surpass a specified min.
(3) Create functions to return the current value of each stat.
(1) Create a script that contains an attack functions that can be called from pre-existing unit state machine logic.
(2) These functions will consider the unit stats of the attacker. For example, when attempting to shoot, the attacker's remaining ammo will be checked.
(1) A class with public functions that can be called to activate abilities.
(2) Be able to create ray cast and projectile abilities respectively.
(3) Be able to adjust name, damage and cooldown of the abilities.
(4) Abilities will have cooldowns during which they cannot be activated.
There are a lot of ways to implement the above elements. The ways I chose were based on these factors:
How much do I already know about implementing such a system, mechanic, or feature?
What kind of resources for learning about the given system, mechanic, or feature do I know of? Or will I need to research?
What kind of dependencies am I dealing with for a given system, mechanic, or feature?
Do I have to wait on someone else to complete a task that mine relies on in order to be implemented?
Is someone else going to be waiting on me to implement a particular task before they can start on theirs?
In the future, what kind of features, systems, or mechanics will rely on what I am doing now?
How flexible does the system need to be?
What kind of performance budget has been assigned to the feature, system, or mechanic that makes up my tasks?
Time to implement
In terms of implementation this first week was not heavy in terms of work load but it was heavy in terms of importance. The way the character stats, combat, and abilities foundations are set up determine the flexibility of our combat system in the future. To that end I did a fair amount more planning before implementation than I normally would.
For character stats I decided to use Unity’s scriptable object system to offer the greatest amount of flexibility for creating different player characters and enemy characters. Scriptable objects are powerful in that they offer the data persistence and the ease of access of xml files while also allowing the execution of code within the scriptable object like a monobehaviour. Another beautiful thing about scriptable objects is that they can be added to the asset creation menu in Unity.
Allowing any designers who want to make a new character to simply go to the create asset menu. Referencing scriptable objects can then be done as if they were a monobehaviour. The only catch is that the data in a scriptable object can be changed permanently at runtime. So there needs to be temporary variables, or a temporary data container, created, or referenced, in the object that performs any operations on data from the scriptable object.
For player units and enemy units to perform basic attacks on each other It was simply a case of adding a few lines of code to the player control. Our AI guy Tyler had already handled target acquisition and created a shooting state for enemies and players to enter into once they have a target in range and in vision. To actually deal damage and manage health checks for death I created a combat utility script that can be accessed from within any script due to its functions being static. Dealing damage, modifying health, modifying ammo, and death are all handled within the combat utility script.
Creating the foundation for abilities was the most challenging task for this week. The design of the game calls for a lot of variety in this department and that means the underlying system needs to support that. So I went for maximum ambiguity where I could, when setting up the base scriptable object class for abilities. Again I decided to use scriptable objects for this system to give as much flexibility as possible to my fellow designers. After having set up the base class I created a ray cast and projectile ability subclass that both inherited from abilities. Creating separate subclasses for abilities based on whether they are ray cast, projectile, AoE, etc. is because the way in which aiming these abilities differ as well as the way in which they target enemies. For each greater archetype of ability there will be a scriptable object that can be created to store the data about the given ability that was just created. For example, a projectile object will need the force at which it is launched, the projectile that will be launched, the aim projectile that will be used to show the trajectory, the cooldown, and the radius of the ability.
Doing the final integration of our work at the end of the week went very smooth which was a great reprieve for some of our team who were really grinding hard all week. This can be attributed to all of us communicated effectively, submitting early and often, and helping each other with errors earlier rather than later.
Thanks for reading and check back next week for another devblog.