Here is the client code
local CharacterFolders = workspace:WaitForChild("Characters")
local Characters = game:GetService("ReplicatedStorage"):WaitForChild("Characters")
local UpdatePosition = game:GetService("ReplicatedStorage"):WaitForChild("UpdatePosition")
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local path = PathfindingService:CreatePath({
["AgentRadius"] = 3,
["AgentHeight"] = 5,
["AgentCanJump"] = true,
["WaypointSpacing"] = 4,
["Costs"] = {
["Water"] = 20
}
})
local chars = {}
local function followPath(destination,Character)
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local humanoid = Character:WaitForChild("Humanoid")
local success, errorMessage = pcall(function()
path:ComputeAsync(Character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
waypoints = path:GetWaypoints()
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
if blockedWaypointIndex >= nextWaypointIndex then
blockedConnection:Disconnect()
followPath(destination,Character)
end
end)
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if nextWaypointIndex < #waypoints then
nextWaypointIndex += 1
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
elseif nextWaypointIndex >= #waypoints then
reachedConnection:Disconnect()
blockedConnection:Disconnect()
UpdatePosition:FireServer(Character.Parent)
followPath(Character.Parent:GetAttribute("Position"),Character)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
for i,folder in pairs(CharacterFolders:GetChildren()) do
if folder:IsA("Folder") then
local model = Characters[folder.Name]:Clone()::Model
local human = model:FindFirstChild("Humanoid")::Humanoid
model:MoveTo(folder:GetAttribute("Position"))
model.Parent = folder
chars[folder] = model
followPath(folder:GetAttribute("Position"),model)
end
end
task.spawn(coroutine.create(function()
workspace.CurrentCamera:GetPropertyChangedSignal("Focus"):Connect(function()
for i,v in pairs(chars) do
if (v.PrimaryPart.Position - workspace.CurrentCamera.Focus.Position).Magnitude > 200 then
v.Parent = game:GetService("ReplicatedStorage")
else
v.Parent = i
end
end
end)
end))
Here is the server code
local UpdatePosition = game:GetService("ReplicatedStorage"):WaitForChild("UpdatePosition")
local characters = {}
function getPosition(folder)
local data = characters[folder]
data = data[math.random(#data)]
local offset = Vector3.new(math.random(-data.Size.X/2,data.Size.X/2),0,math.random(-data.Size.Z/2,data.Size.Z/2))
return data.CFrame:PointToWorldSpace(offset)
end
for i,v in ipairs(script.Parent:GetChildren()) do
if v:IsA("Folder") then
local new = {}
for _,part in ipairs(v:GetChildren()) do
table.insert(new,{["CFrame"]=part.CFrame,["Size"]=part.Size})
part:Destroy()
end
characters[v] = new
v:SetAttribute("Position",getPosition(v))
end
end
UpdatePosition.OnServerEvent:Connect(function(plr,folder)
folder:SetAttribute("Position",getPosition(folder))
end)
But some NPC stop at some point