How To Make A Better AI Flocking System?

I added a sort of flocking system to my AI where they attempt to space themselves from each other instead of bumping into one another.

It kinda works, but it looks weird and “glitchy”.


Here’s the code I used:

while task.wait() do
	local localZombies = {}
	for _, char in ipairs(workspace.AI:GetChildren()) do
		if char and char ~= v and char:IsA("Model") then
			local HRP = char:FindFirstChild("HumanoidRootPart")
			
			if HRP then
				local distance = (char.HumanoidRootPart.Position - HRP.Position).Magnitude

				if distance <= 10 then
					table.insert(localZombies, HRP.Position)
				end
			else
				warn("NO HRP SMHH")
			end
		end
	end
	
	for i,zombie in ipairs(localZombies) do
		local dir = (v.HumanoidRootPart.Position - zombie).Unit
		local nPos = v.HumanoidRootPart.Position + dir
		
		if (v.HumanoidRootPart.Position - zombie).Magnitude < 5 then
			v.Humanoid:MoveTo(nPos)
		end
	end
end
1 Like

Off the top my head the two solutions I think of are either create a kind of tree like structure where the zombies in the back are actually chasing the zombies in front of them. Or you can determine an already spaced out version where each zombie is given a local position and will actually just move towards target + local position.

both those solutions will probably need tweaking to get them to feel good. The first solution might be easier if you intend to implement Pathfinding though.

1 Like

If it’s not random you can use offset attachment points from a “Main” npc, if it’s random then you would still use attachment points but you would need to calculate the points for a npc to fill based off how you want them to flock, e.g hexagonal then linear forwards and backwards offsets

1 Like

How would I be able to do that?

The way I did it was via .Unit, and literally the only reason my thing works is because I put the flocking loop and the actual ai loop in two different loops. It works because it’s rapidly moving to the target then to the flocking position (if you make the AI :MoveTo() the flocking position, it will just go forever in a single direction)

There’s probably a better way to do my flocking system, but I haven’t found it yet.

So for the part you quoted, you essentially have to choose positions that are already spaced out for the zombies. Then you need to pick a position that represents the whole horde. That position can technically be anywhere, but I’d recommend making at the center. Then you take each zombie that’s already spaced out in store its position relative to the center of the horde. (ZomPos - hordePos). Then you pick a destination for the horde to go towards. But have each zombie actually heading towards targetHordePosition + relativeZombiePosition for each zombie. Now each zombie is moving at the same speed towards a predetermined location with no overlaps. You will likely need to edit this a bit because if they hit any obstacles it will break and you’ll have to re-calculate separation.