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)
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.
--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)