Hi everyone,
I'm working with Unreal Engine 4, and I am trying to get a large-scale battle system in place, similar to Total War. Armies will comprise several dozen companies, each containing 200 individual soldiers.
So far, I have managed to get 10k animated soldiers on screen at once with good fps (100fps on a GTX 1080 at 1440p), and I have ditched the use of movement components, instead projecting each soldier onto the navigation mesh to make sure they align with the floor and limiting their movement to it so can't move through solid objects (thereby negating the need to check for environment collisions). Finally, I am using asynchronous hierarchical pathfinding, which allows me to have each individual soldier do their own pathfinding if necessary without causing hitching.
Where I am now stuck a little bit is on how to stop them phasing through each other. I was looking at a flocking algorithm of some sort, but I am not getting the results I need. The game is set during the Napoleonic era, so it is anticipated that soldiers will march in columns and ranks for the most part, and therefore I think I can ditch the cohesion and alignment parts of the algorithm because each soldier will have a specific space in the formation they should stand in, and unless their path is blocked they should just move to that position each time.
The flocking algorithms I've been looking at suggest that for each soldier in the company, I should do something like this:
FVector MySoldierClass::CalculateVelocity()
{
FVector Velocity = FVector(0,0,0);
FVector DesiredMoveDir = (PlaceInFormation - this->Location).GetSafeNormal();
FVector SeparationDir = CalcSeparation();
Velocity = DesiredMoveDir += SeparationDir;
Velocity = Velocity.GetSafeNormal() * MovementSpeed;
return Velocity;
}
FVector MySoldierClass::CalcSeparation()
{
FVector SepDir = FVector(0,0,0);
int32 CollisionCount = 0;
for (MySoldierClass* CheckSoldier : OtherSoldiers)
{
if (CheckSoldier != this)
{
float Dist = FVector::Distance(this->Location, CheckSoldier->Location);
if (Dist < MinimumSpacing)
{
CollisionCount = 0;
FVector ThisSepDir = (this->Location - CheckSoldier->Location).GetSafeNormal();
SepDir += ThisSepDir;
}
}
}
if (CollisionCount > 0)
{
SepDir /= CollisionCount;
SepDir.Normalize();
}
return SepDir;
}
However, this causes all my soldiers to start marching off at an angle. Not sure what I'm doing wrong here, or if the flocking algorithm isn't right for what I want to achieve. All I really want is for soldiers to avoid each other and not clip inside each other when moving around. Maybe there is something really obvious I'm missing?
Thanks!