Our custom tools for designing boss fights


Hello everyone,

we are currently hard at work on a very exciting feature: boss fights! So far, players had to defeat a lot of foes, and as the ultimate test of their abilities and teamwork, they are going to have take on a big baddie!

In this post, we want to give you a glimpse into the workflow and tools we made and are using to create the boss and its behaviour, with a focus on fast iteration and quick balancing.  

SETUP

What we know is that our boss is going to have a variety of different attacks, each with their own unique characteristics. Our approach is primarily concerned with designers being able to set and change these characteristics very quickly to make balancing possible without taking significant amounts of time. The two aspects of this are: an easy to use, intuitive interface for changing relevant data values, and secondly, the possibility to make those changes on the fly, meaning in the play mode of the Unity editor. So, let’s have a look at how these are accomplished by looking at a (partial) example. The attack we are looking at here is a circular area of effect attack that expands over time. The basic data is this: the position, the target radius, the time it takes to fully expand to that radius, and an animation curve describing that expansion over time.

SCRIPTABLE OBJECTS

The underlying data for our boss attacks is utilizing simple Scriptable Objects. These fit our specific needs here very well, seeing that all the balancing and finetuning is confined to the Unity editor. Scriptable Objects also allow us to make and keep changes in play mode. Oftentimes, Scriptable Objects are created by making use of the CreateAssetMenu attribute to then manually create instances of the object. For our boss attacks however, we decided to integrate the creation and destruction of those objects directly into the UI, making it faster and more intuitive to create new attacks. The script we are using for this is a modified version of the one found here: https://wiki.unity3d.com/index.php/CreateScriptableObjectAsset

THE INTERFACE

For the interface we are making use of the OnSceneGUI method that Unity provides. This method can be implemented by any class deriving from the Editor class. In our case it’s a custom inspector for the Boss class. OnSceneGUI is only called when the object is selected, like how OnDrawGizmosSelected works. Inside the OnSceneGUI method we do can several things: we can use the Handles class to make use of various handles for settings positions, rotations, scales and more. But we can also draw any kind of UI we want, making use of Unity’s immediate mode GUI (IMGUI). Let’s see both in action:

To set the position of the attack we can simply draw a PositionHandle and hook it up to our position vector like so:

Vector3 pos = Handles.PositionHandle(bossAttack.SpawnPosition, Quaternion.identity);
bossAttack.SpawnPosition = spawnPosition;

Now, instead of having to set the individual components on our vector via the inspector, we can simply drag the handle around. Additionally, we can also have our handle support basic undo functionality. All we must do is check if the handle has changed i.e. if it has been moved and if so, register the current state of the object with the Unity undo system before making the change:

EditorGUI.BeginChangeCheck();  
Vector3 spawnPosition = Handles.PositionHandle(bossAttack.SpawnPosition, Quaternion.identity);
if (EditorGUI.EndChangeCheck())
{
    Undo.RecordObject(bossAttack, "bossAttack SpawnPosition changed");
    bossAttack.SpawnPosition = spawnPosition;
 }

And of course, you could use the same technique for setting the rotation, scale and, as we do for this example attack, a radius handle, allowing us to set the size of our attack radius by dragging the handle.

Using the handles:

Besides those handles we also need some other interface elements, namely some sliders to adjust float or int values and some buttons to execute a variety of different functionality. For our area-of-effect attack we are drawing a slider for the expansion duration, as well as some general-purpose buttons, more about those in a moment. For the slider we are using the GUI class like so:

Handles.BeginGUI();
float duration = GUI.HorizontalSlider(sliderRect, bossAttack.ExpansionDuration, 0f, 10f);
bossAttack.ExpansionDuration = duration;
Handles.EndGUI();              

The slider here only needs a Rect with a position and a size, the current value and the minimum and maximum values. And of course, we would want to utilize the EditorGUI.BeginChangeCheck and EditorGUI.EndChangeCheck methods to detect when something changes, just like before and then once again register with the Undo system. I have omitted this part from the code to keep it short and simple.

Additionally, there is a set of basic functionalities that is common to all attacks, accessible via buttons. We can firstly create a new instance of the same kind of attack, effectively cloning our attack. Secondly, we can quickly remove an attack, which will also delete the asset. And lastly, we can inspect the asset, by way of opening a simple custom editor window. This custom inspector is important because OnSceneGUI does not play nice with multiple inspectors or a locked inspector. So, in order to inspect an asset while keeping the boss prefab selected to draw our handles and UI, we use this custom window that draws the inspector for whatever object we want to inspect. This also allows easy and quick access to any data which cannot be set directly using the Handles and GUI classes, in our example that would be the animation curve.

Opening and using the custom inspector window:

With all of that we can very rapidly add and delete attacks and tweak existing ones, even in play mode. Other types of attacks do require their own Handle and GUI elements, all depending on the kind of data we want to expose. 

To close things out, let's have a look at everything coming together to configure some attacks.

Setting up the attacks:


Seeing the attacks in action:


STAY TUNED

xDasher on Steam  Follow us on Twitter Join our Discord

Get xDasher (Demo)

Comments

Log in with itch.io to leave a comment.

Wow! This is a cool bit of games engineering ;)