March 13, 2020
This week, amongst other things, I’ve been working on creating a base enemy that can then be quickly adapted to different kinds of foes so that gameplay ideas can be prototyped and tested as quickly as possible.
The idea with the base enemy is to create a default actor that can be extended with extra behaviours/abilities etc. as needed. Variables that are universal across all enemies (health, damage, movement speed, faction etc.) are stored within the base enemy template and then individual values can be adjusted per enemy and new variables also added.
I’m creating the AI for my enemies with Playmaker, which is a visual scripting tool for Unity. Playmaker uses finite state machines (like a flowchart) to tell gameobjects what actions to perform and when. One could argue that finite state machines are a little outdated and inflexible compared to behaviour trees etc. but for me it works well for quickly prototyping the kinds of simple yet distinct enemies that I’m imagining for this game.
Here’s what the base enemy’s main behaviour state machine looks like in Unity:
This base behaviour script is still a work in progress, so it will no doubt grow but ideally any behaviours that are specific to a particular class of enemy or specialist will be added to separately extended scripts and this template version will stay as simple as possible. In the column to the right of the state machine, you can see some of the universal variables that are common to all enemies. In the Inspector, in addition to the main FSM and one where all the base variables are stored, you can see components that cover health, event awareness etc.
Cone of Vision
The base enemy’s cone of vision is held on a child game object called ‘Sight’. I’m using an asset called Sensor Toolkit, which is a really useful set of sensors that allow you to detect colliders and rigidbodies and then feed that info to scripts. On top of detecting whether something is within a certain radius/FOV it can also take into account line of sight which is particularly handy in a game where the world’s geometry is constantly being changed.
Voxel Play, which I’m using to prototype Fronterra, includes a dynamic navmesh which updates whenever the voxel terrain is changed so that AI can continue to path towards their target regardless. Here you can see an enemy adapting to the terrain and finding an alternate way to smack the player in the face!
Colour-Coded Behaviour States
As I did in my previous project, I’m using colours to communicate an AI’s current state as I think it makes it really easy to see when they are changing from one behaviour to another. Currently the base enemy has just 3 moods - green for neutral, yellow for suspicious and red for agro - but the range will grow as development progresses.
Enemies will cooperate if a member of their faction raises an alert or is in danger. When an alert is raised by an enemy, others will determine whether to help or not based on who is calling and how far away they are.
So, now that I have a pretty robust base enemy to build from, I’ve started to think about what kinds of enemies make sense for this game and also how they would interact with each other as well as players. I think that having a varied monster ecology which creates lots of dynamic and interesting situations would make for fascinating gameplay, especially when coupled with the combinatorics of procedural generation and enemy population. I started to put together a chart of enemies which describes not only what they do, but also their relationships with one another, unique loot drops etc.
Here’s a short video showing some of the stuff I mention above:
I’m excited to start creating variants with distinct behaviours. Firstly, I plan to create a ranged, sniper-like enemy and a big, charging enemy that can knock players - and other enemies/NPCs - flying and also smash voxels if they collide with the them while agro’ed. I’d also like to do some rough designs for the monsters in the ecology above and finally I want to flesh out this starter biome and create something that feels more interesting and organic. I’m hoping to find the sweet spot between proc-gen and hand-crafted.