Hey all, I want to help my users in my game figure out why their NPCs are failing to find paths. Right now, it’s very ambiguous as my game is a sandbox tycoon where players created their own tycoon using a placement interface. My internal feedback for when an NPC cannot compute a path is just “This npc failed, but IDK why”.
Since my users are confused, they think its the fault of the game, rather, its likely they slipped up and closed off a path.
I have tried path.blocked but this does me no good if it has already been blocked to begin with.
This is my NPC class moveto function, a lot of it may not make sense but what I’m after is the very bottom line where it tells the user a path was not created. I’d like to give them a visual idea of where it failed, preferably by placing a billboard UI at the object that blocked the path.
function npc:MoveTo(cframe,data)
self.GUID = game.HttpService:GenerateGUID()
self.LastAction = game.ReplicatedStorage.Time.Value
if not data then
data = {
yield = false,
aboutToSit = false,
}
end
if typeof(cframe) == "Vector3" then
cframe = CFrame.new(cframe)
end
if (self.ServerPart.Value-cframe.Position).Magnitude <= 2 then
self:StopMoving()
return
end
if self.PathConnection then
self.PathConnection:Disconnect()
end
local Waypoints = {}
self.Path = PathfindingService:CreatePath(pathParams)
self.Path:ComputeAsync(self.ServerPart.Value,cframe.Position)
self.PathConnection = self.Path.Blocked:Connect(function()
self:Teleport(cframe.Position)
end)
if self.Path.Status == Enum.PathStatus.Success then
Waypoints = self.Path:GetWaypoints()
local waitTime = 0
local tracker = Instance.new("Vector3Value")
tracker.Value = self.ServerPart.Value
for i,v in pairs(Waypoints) do
local distance = (tracker.Value-v.Position).Magnitude
waitTime += ((distance/16))
tracker.Value = v.Position
end
self:SetState("Walk")
self:Replicate("Path",Waypoints,cframe,data.aboutToSit)
local guid = self.GUID
self.ServerPart.Value = cframe.Position
task.spawn(function()
for i=1,#Waypoints do
task.wait(waitTime/#Waypoints)
if guid ~= self.GUID then break end
self.LastAction = game.ReplicatedStorage.Time.Value
end
end)
if data.Yield then
task.wait(waitTime)
if self then
self:StopMoving()
end
else
task.delay(waitTime,function()
if self then
self:StopMoving()
end
end)
end
else
local distance = (self.ServerPart.Value-cframe.Position).Magnitude
local notification = require(Knit.Helpers.NotificationCenter)
if self.Player then
notification:SendNotification(self.Player,"Path Fail","Direct route taken, make sure your paths are clear.",false)
end
task.delay(distance/16,function()
self:Teleport(cframe)
self:StopMoving()
end)
end
end