Random Pathfinding NPCs Appearance

I’ve followed trough an tutorial on youtube on how to make pathfinding npcs and, it worked. But now, I want their appearance to be randomly picked from a series of presets inside a folder.
Here comes the problem… I don’t know how…

This is the script I have used for the NPCs with the failed attempt of making their appearance random:

local PFS = game:GetService("PathfindingService")
local paths = {}
local constraints = {}
local objects = script.Objects:GetDescendants()

for i, v in pairs(script.Constraints:GetDescendants()) do
	local path = PFS:CreatePath()
	path:ComputeAsync(v.Attachment0.Parent.Position, v.Attachment1.Parent.Position)
	paths[#paths + 1] = path
	constraints[#constraints + 1] = v
end

for i, v in pairs(objects) do
	v:Destroy()
end

while true do
	spawn(function()
		local clones = game.ServerStorage.NPC:GetChildren()
**		local clone = clones:Clone()
		clone.Parent = game.Workspace
		local random = math.random(1, #paths)
		local path_chosen = paths[random]
		clone:MoveTo(constraints[random].Attachment0.Parent.Position)
		for i, v in pairs(path_chosen:GetWaypoints()) do
			clone.Humanoid:MoveTo(v.Position)
			clone.Humanoid.MoveToFinished:Wait()
		end
		task.wait(0.1)
		clone:Destroy()
end)
task.wait(10)
end

Any sort of help will be appreciated.

2 Likes

Using :GetChildren() returns a numerically indexed table, so you can just do:

local clone = clones[math.random(#clones)]:Clone()

In some way, it works, it spawns in the NPC’s with the presets but the pathfinding breaks all together, the NPC’s just spawn and stay there, stacking on top of eachother.
I’ve tested it out with the presets and the Roblox built-in rigs. The rigs work but the randomly selected ones don’t.

Pathfinding is tricky.
I suspect the issue could be with your pathing, but can’t be sure. I couldn’t quite understand your use of constraints, or why the objects get destroyed.

This is a simplified version of what you have.

local PFS = game:GetService("PathfindingService")

local pathingFolder = game.Workspace.Pathing -- place parts here for waypoints
local npcFolder = game.ServerStorage.NPC

local waypoints = pathingFolder:GetChildren() -- Get all waypoints

while true do
	spawn(function()
		local clones = npcFolder:GetChildren()
		local clone = clones[math.random(#clones)]:Clone()
		clone.Parent = game.Workspace
		
		local endWaypoint = waypoints[math.random(#waypoints)]

		local path = PFS:CreatePath()

		path:ComputeAsync(clone.HumanoidRootPart.Position, endWaypoint.Position)
		local endWaypoints = path:GetWaypoints()

		for _, waypoint in pairs(endWaypoints) do
			clone.Humanoid:MoveTo(waypoint.Position)
			clone.Humanoid.MoveToFinished:Wait()
		end
		
		clone:Destroy() 
	end)

	wait(10) 
end

This works for me but there’s not a lot of difference. You might be able to adapt this to your version, or perhaps you’ll see something in your use of constraints/objects.

I’d recommend giving this a study:
Character Pathfinding | Documentation - Roblox Creator Hub

So, basically, my system has that destroy thing to correct bad pathways, once the pathway is created the script destroys the parts that created the pathway. For example, an sidewalk with a 90 degree corner, you can’t just leave some walls on the sidewalk so the script destroys them. The constrains just create attachments and give the script some positions to where it could spawn the npcs and where their destination could be.
Anyways, I’ll try your script out, see if it works, If it doesn’t, I’ll get back ASAP.

1 Like

Okay, that makes sense and seems like a solid approach.

Alright so, I have tried your script and It did not spawn any npcs for me. I use r6 rigs and have a 2 layered map (subway and outside). They did not spawn anywhere unfortunately. (I have tried switching the parent of the script, still didn’t work)
Can you give me some specifications on how you made yours work ? Since you said it worked out on your end ?

I did not set the clones position in the script sample, so they would likely be spawning around (0,0,0), or the default baseplate spawn location.

You could make a spawn part, and then position them there after you clone them by adding a apart name SpawnPart to workspace and then adding to your code:

while true do
	spawn(function()
		local clones = npcFolder:GetChildren()
		local clone = clones[math.random(#clones)]:Clone()
		clone.Parent = game.Workspace
        clone.Position = workspace.SpawnPart.Position 
     --rest of code

Well, apparently the rig does not have a “position” property.
Printed out this error:
Position is not a valid member of Model “Workspace.Rig”

Oh yeah, duh! This would work, but we’re getting into messy code.

clone.HumanoidRootPart.Position

Same result unfortunately. Part is properly mentioned in the script, the script does not print any errors and the npcs do not spawn at 0,0,0 either, which is kinda weird.
I’m sorry for this back and forth conversation but it just doesn’t work, at all.

Yeah. I thought we would have a quick solution to your problem. I did not test the code long enough to see that the NPCs were flying, literally. :sweat_smile:

Presetting the position seems to work. You can try this:

local PFS = game:GetService("PathfindingService")

local pathingFolder = game.Workspace.Pathing -- parts
local npcFolder = game.ServerStorage.NPC
local npcSpawnPart = game.Workspace.EnemySpawn

local waypoints = pathingFolder:GetChildren() -- Get all waypoints

for _,npc in ipairs(npcFolder:GetChildren()) do
	local rootPart = npc:FindFirstChild("HumanoidRootPart")
	if rootPart then
		rootPart.Position = npcSpawnPart.Position
	end
end

while true do
	spawn(function()
		local clones = npcFolder:GetChildren()
		local clone = clones[math.random(#clones)]:Clone()
		clone.Parent = game.Workspace

		local endWaypoint = waypoints[math.random(#waypoints)]

		local path = PFS:CreatePath()

		path:ComputeAsync(clone.HumanoidRootPart.Position, endWaypoint.Position)
		local endWaypoints = path:GetWaypoints()

		for _, waypoint in pairs(endWaypoints) do
			clone.Humanoid:MoveTo(waypoint.Position)
			clone.Humanoid.MoveToFinished:Wait()
		end
		
		clone:Destroy() 
	end)

	wait(10) 
end

If it still doesn’t work, idk.
You just have to follow what the errors say and track them back to adjust the code.

1 Like

Very sorry for the late reply, I went to sleep but yeah, now it works as it should.
Thank you very much :smiley:

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.