NPC Raycasting Pathfinding System Help!

  1. What do you want to achieve?
    Right now, I have an NPC that uses a raycast to check if there are any obstacles between them and the player, and if there aren’t, it will start chasing the player by pathfinding to them. (So, if there is a clear line of sight between NPC and player, the NPC will start chasing). I want that while the NPC is chasing the player, if the player goes out of sight of the NPC, the NPC will still continue chasing for a few seconds before stopping.

  2. What is the issue?
    Right now, the NPC stops chasing immediately after the player goes out of sight, which is bad because in-game you can easily evade the NPC by just hiding behind a wall.
    Here is a video of the issue: Broken Monster Showcase - Clipped with Medal.tv

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I can’t figure out how to make the NPC continue chasing the player after it has started, I also couldn’t find any solutions on the devforum. I’d appreciate your help/ideas!

Here is the section of the script that controls the raycast system I said above:

while true do
	local MainTarget = FindNearestBae()

	if MainTarget then
		if not Running then
			Walking = nil
			Running = true
			PlayAnimation(script.Run)
		end

		local DistanceToTarget = (NPC_HRP.Position - MainTarget.Position).Magnitude
		if DistanceToTarget <= NoticeRange then
			local rayDirection = (MainTarget.Position - NPC_HRP.Position)
			local raycastParams = RaycastParams.new()
			raycastParams.FilterType = Enum.RaycastFilterType.Blacklist

			raycastParams.FilterDescendantsInstances = {MainTarget.Parent};

			local raycastResult = workspace:Raycast(NPC_HRP.Position, rayDirection, raycastParams)

			if not raycastResult then
				if DistanceToTarget <= AttackRange then
					if not ChaseMusic.Playing then
						ChaseMusic:Play()
					end
					NPC_Humanoid:MoveTo(MainTarget.Position)
					task.wait()
				else
					local Path = game:GetService("PathfindingService"):CreatePath()
					Path:ComputeAsync(NPC_HRP.Position, MainTarget.Position)
					if Path.Status == Enum.PathStatus.NoPath then
						RandomMove()
					else
						if not ChaseMusic.Playing then
							ChaseMusic:Play()
						end
						local Waypoints = Path:GetWaypoints()
						for i, v in pairs(Waypoints) do
							NextPoint = v
							NPC_Humanoid:MoveTo(v.Position)
							if v.Action == Enum.PathWaypointAction.Jump then
								NPC_Humanoid.Jump = true
							end
							NPC_Humanoid.MoveToFinished:wait()
						end
					end
				end
			else
				Running = nil
				Walking = nil
				RandomMove()
			end
		else
			Running = nil
			Walking = nil
			RandomMove()
		end
	else
		Running = nil
		Walking = nil
		RandomMove()
	end
end
4 Likes
4 Likes

Thanks for the reply, but the NPC already uses the pathfinding service

2 Likes

Do you know how I could implement the pathfinding service again in this situation so that the monster will continue pathfinding after it stops seeing the player?

1 Like

How often you updating the npc’s path? If you get deltaTime, you could create a constant and a counter that continues to arrange a new path in the time the count is above zero, and during the state the target is out of view, you would skip raycasting and just get the distance
I modified your script to perform sort of in this behavior, there is probably mistakes

—if you have more than one entity, you would update the time less frequently for each one

local Chasing = false
local Mem = false

function OnLostSight()
    if Mem ~= true then return end
    Mem = true
    local catchTime = 5
    local time = tick()
    local dt = 0
    delay(0, function()
        while catchTime > 0 do
        if (NPC_HRP.Position - MainTarget.Position).Magnitude > NoticeRange
        if catchTime <= 0 then Chasing = false ChaseMusic:Stop() Mem = nil break end
            dt = time - tick()
            catchTime -= dt
            time += dt
        task.wait(0.1)
    end
    end) 
end

local function Chase()
    if DistanceToTarget <= AttackRange then
					if not ChaseMusic.Playing then
                        Chasing = true
						ChaseMusic:Play()
					end
					NPC_Humanoid:MoveTo(MainTarget.Position)
					task.wait()
				else
					local Path = game:GetService("PathfindingService"):CreatePath()
					Path:ComputeAsync(NPC_HRP.Position, MainTarget.Position)
					if Path.Status == Enum.PathStatus.NoPath then
						RandomMove()
					else
						if not ChaseMusic.Playing then
							ChaseMusic:Play()
						end
						local Waypoints = Path:GetWaypoints()
						for i, v in pairs(Waypoints) do
							NextPoint = v
							NPC_Humanoid:MoveTo(v.Position)
							if v.Action == Enum.PathWaypointAction.Jump then
								NPC_Humanoid.Jump = true
							end
							NPC_Humanoid.MoveToFinished:wait()
						end
					end
				end
end


while true do
	local MainTarget = FindNearestBae()

	if MainTarget then
		if not Running then
			Walking = nil
			Running = true
			PlayAnimation(script.Run)
		end

		local DistanceToTarget = (NPC_HRP.Position - MainTarget.Position).Magnitude
		if DistanceToTarget <= NoticeRange or Chasing then
			local rayDirection = (MainTarget.Position - NPC_HRP.Position)
			local raycastParams = RaycastParams.new()
			raycastParams.FilterType = Enum.RaycastFilterType.Blacklist

			raycastParams.FilterDescendantsInstances = {MainTarget.Parent};

			local raycastResult = workspace:Raycast(NPC_HRP.Position, rayDirection, raycastParams)

			if not raycastResult or Chasing then
			    Chase()
                OnSightLost()
			else
				Running = nil
				Walking = nil
				RandomMove()
			end
		else
			Running = nil
			Walking = nil
			RandomMove()
		end
	else
		Running = nil
		Walking = nil
		RandomMove()
	end
end

Ohh I see! Thanks for the help