I’d like to take some time today to review some changes I recently made to two key systems. The first being the Attack Move AI, the other being a sub-component of the movement system, that I like to call Unit Slow.
Attack Move is a form of movement command that makes a unit move to a destination, attacking enemies on the way. There’s a lot more to that, but on the surface is seems pretty simple.
Unit Slow is a system I put in place to make formations matter. Basically, when non-friendly units collide, their movement should slow down such that they aren’t able to penetrate a formation. This is significant because a lot of the game is about defending chokepoints or guarding vulnerable units.
Let’s take an in-depth look at these systems with two recent gifs taken from my Unity editor on the testing map. Note that these gifs were taken with the camera pointing perfectly down with the camera set to isometric.
Firstly, lets understand what’s going on here. On the left side we’ve got some Human Champions which I control. On the right side we’ve got some Undead Warriors which the game server controls, and which do not have any AI of their own other than what they normally have.
The blue lines coming from the Champions indicate the position the unit would like to move to. In this case these indicate Attack Move positions when we’re moving towards the Undead Warriors, and regular Move positions when we’re moving away.
Now let’s take a look at just a single frame of that gif to understand why I’m excited about these changes.
If you observer unit A, you’ll notice I’ve drawn a red circle around it. This circle indicates its aggression range, which we use to determine the limit of how far it looks for things to attack. Basically, unit A is only aware of things within this circle.
Now, if our logic was simple, we’d just calculate the distance to the enemies within the circle and pick the closest one. If that were the case, unit A would attack either Unit B or Unit C.
You might think, just tell it to attack the unit closest to the attack move destination. In that case, we’d be attacking unit E, which also wouldn’t be desirable.
The update in the logic that I’ve recently written makes it such that Unit A considers not only the distance, but also the angle from its destination. It combines these numbers into a unified score, and evaluates enemies based on this criteria.
The reason I’m so excited about these changes it that it makes units attack-move in the intended direction of the player. If you watch the gif a few times you’ll see that you can choose how to attack the enemy based on how you draw your attack-move formation. If you go with a wide formation you’ll spread your units evenly, and if you make a tight attack-move formation, you’ll have the clump. Now the player has a better, more finite level of control over their units.
Next, lets look at the Unit Slow system and the changes I’ve made.
Firstly, lets look at the gif. What you’ll notice is that the Champions approach the wall of Undead Warriors, collide, and then slow down. Eventually they stop trying to move, and switch over from the Move behaviour to Idle, which lets the auto attack nearby enemies.
To understand the slow system, lets take another look at a diagram and walk through some example scenarios.
In all four scenarios, we have unit A which is trying to move north, and Unit B and C which are hostile enemy units holding their position.
Scenarios 1, 2, and 3
Unit A is moving directly north and colliding with Unit B. If we calculate the Vector3.Dot(), we’ll get pretty much 1 as a return value.
If we do the same for Scenarios 2 and 3, we’ll get respective Vector3.Dot values of (roughly) 0.7, and 0.3.
The reason I mention Vector3.Dot is because I use that to determine how ‘in the way’ another Unit is. Unit A knows its colliding with unit B, and it knows the Dot value of the relationship. So, we slow the unit depending on the angle to the colliding enemies.
What this effectively does is allows units to slip around each other when the relationship is one to one like in scenarios 1, 2, and 3. However, things change when we look at multi-unit collisions.
In scenario 4 we’ve got Unit A colliding with two units. The logic behind our system does the same thing as in scenarios 1, 2, and 3, but the slow increases as more enemies collide with Unit A.
Effectively, this means that if we’ve got a good tight formation wall, where 2 or even 3 units are colliding with an enemy, we’ll be able to prevent an enemy from just pushing through our infantry line. Some of this gets a bit more complicated when we consider unit movement speed and mass, but for now we’ll keep it simple.
The last thing I wanted to point out was that when our Champions turn away from the Undead Warrior wall, they do so quickly. The slow system has been updated to not slow the unit when moving away from enemies. It used to be that when you tried to disengage, the system would continue to slow you even though you were moving in the opposite direction of the enemy.
All in all, I think these two changes will have a major impact on how the game plays and how satisfied players are with units carrying out their desired commands.
I hope some of this helps other developers and future players understand some of the logic of the physics and AI that exist within Salt the Earth.