I thought of this script which includes npc pathfinding and a function for chatting with other npcs. But would it be more optimal for it to be a central script (a script controlling said functions across multiple characters). Or if all the characters each had a copy of the script?
It will barely matter in terms of how much processing and memory it uses. It would be easier to maintain it if it’s one script though since any changes will affect everyone immediately.
How would i go about this? Like pathfinding like 10 characters?
The very simple way that is almost like using a single script is to just create a function that is basically a script you would run on each of them, then task.spawn or whatever passing in the NPC it controls to the function. Now this function controls everything but is scheduled to run like different scripts, but from the same script. The other approaches I can think of now boil down the same idea except they may split off something like pathfinding to run by itself or just divide the work slightly differently but fundamentally the same idea, spawn a function that manages the NPC per NPC. It’s fine if this function never returns until the NPC dies or unloads.
Careful with network usage and replication. Moving 10 npc may not seem that great but as you’ll potentially want more, eventually replication will start taking a toll on network receiving.
Don’t do this, this is very unoptimized and causes a lot of lag.
Instead you should use events to handle pathfinding. All done within a single script of course.
I have developped the pathfinding like this the other day so here’s my code. I want you to look at how it disconnects once it reaches its destination, gets blocked, or changes
local WanderingNPCS = {
--an array of rigs.
workspace.Rig
}
local function Pathfind(npc:Model, pos)
local VecObj:Vector3Value = npc:FindFirstChild("PathfindTo")
VecObj.Value = pos
local Humanoid = npc:FindFirstChildOfClass("Humanoid")
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local TouchedConnection
local touched = false
local Path = PathfindingService:CreatePath({
AgentRadius = 2,
AgentHeight = 5,
AgentCanJump = true,
AgentCanClimb = true,
Costs = Costs
})
local function FollowPath(destination)
if Humanoid.Sit == true then
Humanoid.Jump = true
end
local suc, err = pcall(function()
return Path:ComputeAsync(npc.PrimaryPart.Position, destination)
end)
if suc and Path.Status == Enum.PathStatus.Success then
waypoints = Path:GetWaypoints()
blockedConnection = Path.Blocked:Connect(function(blockedWaypointIndex)
if blockedWaypointIndex >= nextWaypointIndex then
FollowPath(destination) --try again
blockedConnection:Disconnect()
end
end)
--TODO: Make it so that npcs don't bump into eachother.
--Maybe make the npc move right for a bit when they touched another HumanoidRootPart?
if not reachedConnection then
reachedConnection = Humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints and pos == VecObj.Value then
nextWaypointIndex += 1
if npc.Humanoid.Sit == true or waypoints[nextWaypointIndex].Action == Enum.PathWaypointAction.Jump then
npc.Humanoid.Jump = true
end
Humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
task.wait(0.5)
if npc.Humanoid.WalkToPoint.Y > npc.HumanoidRootPart.Position.Y then
npc.Humanoid.Jump = true
end
else
blockedConnection:Disconnect()
reachedConnection:Disconnect()
end
end)
end
--print(waypoints)
nextWaypointIndex = 2
Humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", err, destination)
end
end
FollowPath(pos)
end
local function Wander()
for _, npc in WanderingNPCS do
if npc.Humanoid.Sit == true then
npc.Humanoid.Jump = true
end
Pathfind(npc, Locations[math.random(1, #Locations)].Position)
end
end
while true do
print("New location")
Wander()
task.wait(45)
end
I do not know how you would acheive the chatting feature but maybe edit the code and have that functionality?
While true you should handle the path itself with events, I meant this more in the sense of each NPC running it’s own code. So that loop where you are calling path on each NPC is handled internally by each NPC so they can chat independently.
So basically what you wrote except put the logic for each NPC at the same spot your wander function is but have it for each npc so it can pick what to do when it’s path is finished.
You can write your own dispatcher to handle this (like you are doing for your walking) but it won’t be that much more performant than just letting the Roblox code dispatcher schedule the NPC code to run.
Like this psuedocode
local handle PC(npc)
while true do
task.wait() --dont let worst case scenario crash the game
local target = pickTalkPartner()
walkTo(target) --handles pathfinding and pathwalk, returns when done
chat(target)
end
end
Then just task.spawn that for each NPC. Make sure it stops when the NPC dies though.
Could try and find 2 npcs and make them interact
I never thought of using events, I’ll look into it though