NPC Spawning Clumping

I’m trying to randomly spawn npcs across a part, however when I spawn them they clump together. Here’s my code


--DevTops 2020
--[[

Spawns npcs based off the size of the volume and the config

]]


-- // Settings \\ --
local maxSpawned = 30


function spawnThing()
	local npcs = script.Parent:WaitForChild("Configuration"):WaitForChild("NPCPointer").Value
	local new = npcs:GetChildren()[math.random(1, #npcs:GetChildren())]:Clone()

	new.Parent = script.Parent:WaitForChild("npcs")
	
	local size = script.Parent.Size
	local pos = script.Parent.Position
	
	local x = math.random(-size.X/2, size.X/2) + pos.X
	local z = math.random(-size.Z/2, size.Z/2) + pos.Z
	
	new:WaitForChild("HumanoidRootPart", math.huge).CFrame = CFrame.new(Vector3.new(x, pos.Y, z))
end

for i=1, maxSpawned do
	spawnThing()
end

script.Parent:WaitForChild("npcs").ChildRemoved:Connect(function(child)
	spawnThing()
end)

It spawns “maxSpawned” npcs, then spawns a new one everytime one “dies” or is deleted.
Here’s video of what is happening.

you can see when I delete all of them, they spawn in a huge clump, even though it’s math.random(), this also happens when the game starts, even though I don’t have video of it.

also here’s the movement script for the npcs


--DevTops 2020

-- // Settings \\ --
local maxDistance = {10, 30}
----------------------

-- // ENV Settings \\ --
local this = script.Parent
local thisHum = script.Parent:WaitForChild("Humanoid")
local thisHumRoot = this:WaitForChild("HumanoidRootPart")

function movement()
	local currentPosition = thisHumRoot.Position
	local distance = math.random(maxDistance[1], maxDistance[2])
	local newXDistance = math.random(-distance, distance)
	local newZDistance = math.random(-distance, distance)
	local newPosition = Vector3.new(newXDistance+currentPosition.X, currentPosition.Y, newZDistance+currentPosition.Z)
	thisHum:MoveTo(newPosition)
end

function mainLoop()
	if math.random(0, 1000) >= 975 then
		movement()
	end
end
game:GetService("RunService").Heartbeat:Connect(mainLoop)

What type of value are you talking about and can you make the part visible so I could see where you want them to spawn?

It’s an object value which points to a folder containing the NPCS also yes

try to put in some kind of print to see if its the randomization thats causing problems or the spawning itself

I did and it prints the same thing 30 times

I think I’ve found the issue, it’s with the way math.random works, I believe it’s based off a randomness engine that uses time to generate the number, I added a small wait and it worked. I’m currently implementing it.

you could add this infront of every math.random


Just put something like os.time or somthing in there and you will get a newly generated seed everytime

1 Like
--DevTops 2020
--[[

Spawns npcs based off the size of the volume and the config

]]


-- // Settings \\ --
local maxSpawned = 30


-- // ENV Settings \\ --
local needSpawned = 0
local stop = true

function spawnThing()
	math.randomseed(needSpawned)
	local npcs = script.Parent:WaitForChild("Configuration"):WaitForChild("NPCPointer").Value
	local new = npcs:GetChildren()[math.random(1, #npcs:GetChildren())]:Clone()

	new.Parent = script.Parent:WaitForChild("npcs")
	
	local size = script.Parent.Size
	local pos = script.Parent.Position
	
	local x = math.random(-size.X/2, size.X/2) + pos.X
	local z = math.random(-size.Z/2, size.Z/2) + pos.Z
	
	new:WaitForChild("HumanoidRootPart", math.huge).CFrame = CFrame.new(Vector3.new(x, pos.Y, z))
end

needSpawned = maxSpawned

script.Parent:WaitForChild("npcs").ChildRemoved:Connect(function(child)
	needSpawned = needSpawned + 1
end)

game:GetService("RunService").Heartbeat:Connect(function()
	if needSpawned > 0 and stop then
		stop = false
		for i=1, needSpawned do
			spawnThing()
			wait(0.1)
		end
		needSpawned = 0
		stop = true
	end
end)

Updated it to work, atleast to my standards

1 Like