Those who live in storybooks face a lot of consequences when their happy-ending vanishes, and one of them is that the world suddenly becomes swarmed with minions. Fields of flowers that were once peaceful retreats become the stuff of nightmares as anyone wandering too close to one of these bad-guys will quickly find themselves in a heated battle. That's why, for the most part, the NPCs you come across in Book Ends will be taking shelter in their houses until the area outside is free from danger.
Finding balance between the player's progression and the minions they will face is a time-consuming process, so I've built an admin system for my game that allows me to easily make adjustments and test them in a small scene. The admin system is a separate scene in Unity that I can run and make quick changes to hit points, strength, etc and have those changes immediately reflected in game play. I can select a particular enemy, make adjustments, and then very quickly test them out to make sure things feel balanced insofar as gameplay.
As an example, I was recently playing through the dungeon level in which I wanted to have a large number of snakes just wandering through. As I placed more and more of these snakes and then tested out the level, I found that pulling aggro for a handful of snakes at a time proved to result in a rather quick death. This was very easily fixed via my admin system; I simply adjusted the vitality and strength stats for the snake, which in-turn meant they had fewer hit points and dealt less damage. What resulted was that I could have a room full of snakes swarm the player all at once without the player being dealt a fast and unfair death.
This admin system extends to all items, bosses (more on them in a bit) and character classes (the above video was taken a while ago and a lot has been added since). I eventually hope to extend it to include damage/radius/etc. of spells and any dialogue as well. Being a solo developer, I find it worthwhile to put the time in to make things easier going forward, and knowing that balance can require a lot of time to fine-tune, I figured anything I could do alleviate the burden would be a huge help in the long-run. In fact, I've only touched on what this admin system can do so far, and already it has proven its worth. As a result of how easy it is to use, I ended up changing my entire enemy-spawning system to work around the data it creates: my spawn points now all have the option of spawning a specific a random enemy from a predetermined list, or a random enemy of a particular difficulty. This enables me to, for instance, place a number of spawn points around the world and ensure that they will all be a fair fight. If I place 100 spawn points with a difficulty setting that includes snakes, bats and crows, I may later decide to up the difficulty of the snake; this improved spawning system will automatically recognize that snakes can no longer be spawned here due to the fact they would be too difficult for the player to fight at this point in the game. I can also do the opposite and decide later on that skeletons should be a lower difficulty setting, and that would make them candidates for spawning at those particular points.
While the player characters themselves are using Unity's NavMesh Agent for movement (at least in the case of mouse input), the enemies themselves are using A* Pathfinding. There were two things that were pretty important to me when it came to the enemies, the first being that I wanted the option to have a lot of them. I wanted scenarios in which the player would be swarmed, creating moments in which the player might decide to hold off on casting a spell at any given time to ensure their AoE was charged and ready in the event they pulled the attention of a dozen minions at once.
Naturally, enemies start off in a wander mode in which they are basically patrolling an area looking for anything to fight. Once the player moves within their aggro radius, the enemy becomes aware of the player and moves in to attack; they also alert any other enemies that are within their aggro radius, and the aggro radius itself is easily adjusted via my admin system.
Once aware of the player, the minion will move into their assigned attack range and once there will start to randomly "roll" for their next action. Some enemies prefer to stay at range while others charge in to get up-close and personal.
As you can see from the GIF above, the enemy will chase down a player that is on the run until they are within range again. This is the same system that governs whether a playable character is ranged, but just has a bit of AI thrown on top of it. Again, this allows me to keep things as simple as possible, since any adjustments to the attack system itself will be reflected in the character classes as well as the minions themselves.
I will go into more depth on bosses in a future article, but for the purposes of this post, bosses are basically souped-up minions. They look more menacing, are generally much larger in physical size than the player themselves, and - most notably - are capable of spawning minions while in the heat of battle. Their AI is the same system as the minions, but via my admin system I have given them more powerful spells and used higher values for their stats, which results in them being more of a challenge to defeat. As far as programming goes, there is nothing special about them (yet) aside from the fact that there will likely be a small cut-scene after their deaths.
Bear in mind, a lot of these GIFs were taken as development was taking place and are not a great example of the current state of the project. My goal with articles is to first share everything that has happened in development up to January of this year, at which time I will start posting articles whose theme centers around what I have been developing most recently.
As is common among RPG's, those enemies you defeat may sometimes spawn some nice loot for you as a reward. Again, this is fairly easy to modify via my admin system and much like the attack system is shared with the playable characters, the loot system itself is shared among enemies, treasure chests and destructibles (barrels, crates, etc.). I will eventually leverage a system similar to the level of minions that will calculate a value for each item based on the stat bonuses it provides and that value will determine which items are spawned by what.
I can also specifically set the loot for each spawned enemy, which in the case of bosses is absolutely necessary since they will likely drop items that are important to the story-line itself. Gold is also randomly spawned and the amount of gold spawned is directly related to the level of the minion in the case of those, or the level of the player in the case crates and barrels.
So far I am quite happy with how all of these systems tie together, but I also know there is a lot of work in the months ahead to get everything fine-tuned. Work as a freelance developer has kept me very busy this last month, so I have not had much time at all to really focus on continuing development of Book Ends. What I have done is spend 30min-1hr each day after work to focus on lighting. Until recently there were no lightmaps for anything, and I've been spending this bit of time each night to fix that.
The picture above shows my progress thus far but there are still several things I need to adjust; this screen looks exactly how I want it to on one of my monitors but looks washed out on another, and my goal is to find a happy medium between those monitors as well as my cell phone and my television, which all have varying contrast/brightness/etc.
Previously, this scene was rendering ~100 real-time shadows and that number is now down to about a dozen, which will provide a nice boost in performance on older/slower machines that weren't designed as gaming rigs. My goal is to get the game to run at a decent framerate on my mobile device; I'm not sure I can pull that off, but it is a goal I don't really have any intention of achieving either; it serves more as a standard by which I measure performance. The goal is to leverage the low-poly nature of the game to allow it to run as wide a swath of machines as possible, so I've set my bar to high with the expectation of failure for the sake of ensuring I get as good a result as I can when it comes to framerates.
This coming week I hope to share another article that focuses more on the book that this game is centered around, which is a playable level within the game itself. After that I hope to post an article highlighting the coop setup and how players will be able to work together to give this story book world its happy-ending back.