Website/Blog about the things you need to know to make a modern RTS game
Steering Behaviours: Flocking
03 Jan 2014
Flocking behaviours are a subset of steering behaviours where we consider the locations of our neighbouring agents to decide our forces. They are modelled of how flocks of birds work.
Again, a great reference from these is this video of Graham Penthenys GDC2013 presentation, or grab the slides.
We are going to implement the following:
Separation - Move away from those entities we are too close too
Cohesion - Move nearer to those entities we are near but not near enough to
Alignment - Change our direction to be closer to our neighbours
These will get our entities moving around grouped together. Check out the Completed Example
Let’s look at each of these behaviours individually first.
Separation
Separation calculates a force to move away from all of our neighbours. We do this by calculating a force from them to us and scaling it so the force is greater the nearer they are.
Cohesion
Cohesion calculates a force that will bring us closer to our neighbours, so we move together as a group rather than individually. This is the opposite of what separation is trying to do, using them together is important but can tricky. We cover this later.
Cohesion calculates the average position of our neighbours and ourself, and steers us towards it
Alignment
Alignment calculates a force so that our direction is closer to our neighbours. It does this similar to cohesion, but by summing up the direction vectors (normalised velocities) of ourself and our neighbours and working out the average direction.
Cohesion vs Separation and other behaviours
As mentioned under cohesion above, in a situation such as this:
The agents at the front of the pack (far right) will have a cohesion force pulling them away from their seek target. This can mean that they do not reach their top speed as there is always a force slowing them down.
The solution I’ve decided upon is to scale down the effect of cohesion. For our purposes cohesion is not super important. So long as our units don’t spread apart too much while moving then we are doing good.
To implement this and to combine our steering behaviours together, we change our main loop as follows
You can see we have split our loop in two: First we calculate the forces on all of the agents, then we apply them. We must do it in two steps so that all agents see a consistent view of the world when calculating their behaviours.
Using this in a real RTS
I haven’t done this yet, but here are some notes.
Cohesion and Alignment probably only want to be concerned with other agents going to a similar location as us, otherwise we’ll get caught up when other agents move past.
Performance considerations
Each of our behaviours works out the agents neighbours in a very inefficient way, and it is done multiple times every tick.
Instead we should store our agents in a data structure that provides efficient spatial searching (Quadtree, Cell Binning, Wikipedia: Spatial index).
We also don’t need to calculate the neighbours every tick, we should be able to just recalculate them every couple and still have a good looking simulation.
Better than seek
For a real RTS there will probably be obstacles in the way that we need to path around. We’ll need to avoid these when we are close to them, and we’ll need to work out an efficient path to our target. We’ll come back to these in future articles!