I’m not sure if I’ve implemented this wrong, but this seems to break the entire navigation system. Instead of the NPC switching smoothly between AI navigations and simple Humanoid:MoveTo(player)
, the NPC no longer uses AI navigation, although it is running the code, and it is much buggier than before. The old code functions better, but it freezes at the Humanoid.MoveToFinished:Wait()
line, making it unusable as well.
local function pathToTarget(char)
local position = monster.Position
local player = PlayerService:GetPlayerFromCharacter(char)
local targetPosition = char:WaitForChild("HumanoidRootPart").Position or char:WaitForChild("Torso").Position
path:ComputeAsync(position, targetPosition) --Create path
local waypoints = path:GetWaypoints()
for i, waypoint in pairs(waypoints) do --This loop makes the monster follow the waypoints to the player it is chasing.
print("Running Waypoints")
humanoid:MoveTo(waypoint.Position) --Moves NPC
if waypoint.Action == Enum.PathWaypointAction.Jump then --If jumping is required, make the NPC jump.
humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
wConnection = humanoid.MoveToFinished:connect(function() --Honestly, I don't even know what this does.
print("Does something")
didReach = true
wConnection:Disconnect()
wConnection = nil
end)
spawn(function() --This spawns a corountine which "might" fix the error where humanoid.MoveToFinished:Wait() fails.
print("Function spawned")
while not didReach do
if not (humanoid and humanoid.Parent) then --I don't even know what this is supposed to do.
break
end
print("still going")
wait(5)
print("Trying again to move to position")
humanoid:MoveTo(waypoint.Position) --Try again to move to position
end
if wConnection then
print("Breaking Connection")
wConnection:Disconnect()
wConnection = nil
end
end)
print("Done")
--humanoid.MoveToFinished:Wait()
end
return
end
The NPC also appears to “stutter” or freeze at times, like it is lagging or something. Additionally, the code occasionally throws the error Workspace.NPC.Navigate:29: attempt to index nil with 'Disconnect'
. Which is coming from this block of code:
wConnection = humanoid.MoveToFinished:connect(function() --Honestly, I don't even know what this does.
print("Does something")
didReach = true
wConnection:Disconnect() --This is throwing an error.
wConnection = nil
end)
The game will also hang under certain circumstances, and the NPC’s navigation fails. You can see that in this video:
If you need to see the code in context, I’ve included this script below.
--Variables
local PlayerService = game:GetService("Players")
local pathFindingService = game:GetService("PathfindingService")
local humanoid = script.Parent.Humanoid
local monster = script.Parent:FindFirstChild("HumanoidRootPart") or script.Parent:FindFirstChild("Torso")
local CollectionService = game:GetService("CollectionService")
local RunService = game:GetService("RunService")
local PlayerTag = "PLAYER"
local path = pathFindingService:CreatePath()
local didReach = false
--Functions
local function pathToTarget(char)
local position = monster.Position
local player = PlayerService:GetPlayerFromCharacter(char)
local targetPosition = char:WaitForChild("HumanoidRootPart").Position or char:WaitForChild("Torso").Position
path:ComputeAsync(position, targetPosition) --Create path
local waypoints = path:GetWaypoints()
for i, waypoint in pairs(waypoints) do --This loop makes the monster follow the waypoints to the player it is chasing.
print("Running Waypoints")
humanoid:MoveTo(waypoint.Position) --Moves NPC
if waypoint.Action == Enum.PathWaypointAction.Jump then --If jumping is required, make the NPC jump.
humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
wConnection = humanoid.MoveToFinished:connect(function() --Honestly, I don't even know what this does.
print("Does something")
didReach = true
wConnection:Disconnect()
wConnection = nil
end)
spawn(function() --This spawns a corountine which "might" fix the error where humanoid.MoveToFinished:Wait() fails.
print("Function spawned")
while not didReach do
if not (humanoid and humanoid.Parent) then --I don't even know what this is supposed to do.
break
end
print("still going")
wait(5)
print("Trying again to move to position")
humanoid:MoveTo(waypoint.Position) --Try again to move to position
end
if wConnection then
print("Breaking Connection")
wConnection:Disconnect()
wConnection = nil
end
end)
print("Done")
--humanoid.MoveToFinished:Wait()
end
return
end
local function raycastchase(target)
local ignorelist = {monster}
if target == nil then --If called without a target, return and try again.
return
end
local currentTarget = target:FindFirstChild("HumanoidRootPart") or target:FindFirstChild("Torso")
local v2root = currentTarget.Position - monster.Position
local ray = Ray.new(monster.Position, v2root.Unit * 800)
local hit, position = workspace:FindPartOnRayWithIgnoreList(ray, ignorelist)
if hit then
if hit:IsDescendantOf(currentTarget.Parent) then --If the player is within sight, chase them directly.
humanoid:MoveTo(currentTarget.Position)
else -- If the player is not within signt, create a path and follow them.
pathToTarget(target)
end
end
return
end
--Looping Code (start here)
while true do
RunService.Heartbeat:Wait() --Ensures code is not run too frequently, but it should be updated as quickly as possible.
local min = math.huge
local char = nil
for i, character in pairs(CollectionService:GetTagged(PlayerTag)) do --Gets all living/targetable players in-game
local d = (character.PrimaryPart.Position - monster.Position).Magnitude --Determines the distance to each player
if d < min then
min = d
char = character
end
end
raycastchase(char) --Sends the closest player to the rest of the code.
end
Sorry about the huge chunk of code and stuff above, but I’m still not quite sure what exactly is malfunctioning, so I thought it best to include as much as possible.