Flocking Behavior Boid

I cannot figure out why these boids dont bounce off or look in their own direction.

https://gyazo.com/a90c444a1ac4320efa6e3835b4e446ca

--//Services
local runService = game:GetService("RunService")

local boids = {}
local MaxVelocity = 2

local deltaTime = 0

local function cohesionBehavior(boid, radius)
	local found = 0
	local average = Vector3.new()
	for other, data in pairs(boids) do
		if other ~= boid then
			local diff = other.Position - boid.Position
			if diff.Magnitude < radius then
				average += diff
				found += 1
			end
		end
	end
	
	if found > 0 then
		average = average / found
		boids[boid].velocity += Vector3.new():Lerp(average, average.Magnitude / radius)
	end
end

local function aligmentBehavior(boid, radius)
	local found = 0
	local average = Vector3.new()
	for other, data in pairs(boids) do
		if other ~= boid then
			local diff = other.Position - boid.Position
			if diff.Magnitude < radius then
				average += data.velocity
				found += 1
			end
		end
	end

	if found > 0 then
		average = average / found
		boids[boid].velocity += boids[boid].velocity:Lerp(average, deltaTime)
	end
end

local function seperateBehavior(boid, force, radius)
	local found = 0
	local average = Vector3.new()
	for other, data in pairs(boids) do
		if other ~= boid then
			local diff = other.Position - boid.Position
			if diff.Magnitude < radius then
				average += diff
				found += 1
			end
		end
	end

	if found > 0 then
		average = average / found
		boids[boid].velocity -= Vector3.new():Lerp(average, average.Magnitude / radius) * force
	end
end

function containerBehavior(boid, force, radius)
	if boid.Position.Magnitude > radius then
		boids[boid].velocity += boid.Position.Unit * (radius - boid.Position.Magnitude) * force * deltaTime
	end
end

local function getRandomNumber()
	return math.random(-script:GetAttribute("containerRange"), script:GetAttribute("containerRange"))
end

--//Events
for i = 1, script:GetAttribute("boidAmount") do
	local part = Instance.new("Part")
	part.Anchored = true
	part.CanCollide = false
	part.CFrame = CFrame.new(getRandomNumber(),getRandomNumber(),getRandomNumber())
	part.CFrame = CFrame.lookAt(part.Position, Vector3.new(math.random(),math.random(),math.random()))
	part.Size = Vector3.new(2,2,2)
	part.Name = "Boid"
	part.Parent = game.Workspace.Boids
end

for _, boid in pairs(game.Workspace:WaitForChild("Boids"):GetChildren()) do
	boids[boid] = {
		velocity = Vector3.new(math.random(),math.random(),math.random());
	}
end

runService.Heartbeat:connect(function(dt) 
	for boid, data in pairs(boids) do
		cohesionBehavior(boid, script:GetAttribute("cohesionRange"))
		aligmentBehavior(boid, script:GetAttribute("aligmentRange"))
		seperateBehavior(boid, script:GetAttribute("repilsionForce"), script:GetAttribute("seperateRange"))
		containerBehavior(boid, script:GetAttribute("boundaryForce"), script:GetAttribute("containerRange"))
		
		if data.velocity.Magnitude > MaxVelocity then
			data.velocity = data.velocity.Unit * MaxVelocity
		end
		
		boid.Position += data.velocity * (dt*script:GetAttribute("speed"))
		boid.CFrame = CFrame.lookAt(boid.Position, data.velocity)
	
		deltaTime = dt
	end
end)
1 Like