Humanoid.MoveToFinished:Wait() Doesn't Fire Properly

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.

1 Like