How to make an npc see a player within their FOV instead of a single raycast

I’m trying to make a system where there is an NPC walking back and forth from point A to point B, and when they see the player they will start chasing them.

My system works, however it is really easy to not get spotted as I am using Raycasting to check if there is a player in front of them, meaning that they will only start chasing the player once the player is directly in front of them, and this is my issue.

As far as I know, there aren’t any other tutorials or posts on this, so I have made one myself as a last resort.

Here is the script that casts the ray:

local filter = {guard} -- the npc that is detecting the player
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Exclude
params.FilterDescendantsInstances = filter
local ray = workspace:Raycast(guard.Head.Position, guard.Head.CFrame.LookVector * 12.5, params)
			
if ray and ray.Instance and game.Players:GetPlayerFromCharacter(ray.Instance.Parent) then
    chasing = true
    humanoid:MoveTo(closestPlayer.Character.HumanoidRootPart.Position)
    break
else
    chasing = false
end

Any help or hint is appreciated. Many Thanks.

2 Likes

You could either amend your current ray cast script to fire rays in a cone, rather than a single line, which would create the FOV effect you were looking for, or create a hitbox part in the shape of a cone and use that as the form of detection but I would recommend firing ray casts in a cone as it’s more reliable.

This post might have what you need to create ray casts that fire in a cone, if not, there’s many other posts that would have the necessary information.

2 Likes

After some hassle, I managed to get a system in place that I liked without really looking at other tutorials. I knew what I wanted but didn’t know how to get there so I did testing and came with a solution. Here is the script that I ended up creating (inside of a part due to testing)

local function rayFunction(angle, castAmount)
	local current = 0-math.abs(angle)
	for i=1, castAmount do
		local filter = {script.Parent, workspace.test}
		local params = RaycastParams.new()
		params.FilterType = Enum.RaycastFilterType.Exclude
		params.FilterDescendantsInstances = filter
		
		local rayCFrame = script.Parent.CFrame
		local rayAngle = rayCFrame * CFrame.Angles(0, math.rad(current), 0)

		local ray = workspace:Raycast(script.Parent.Position, rayAngle.LookVector * 20, params)
		
		if ray and ray.Instance and game.Players:GetPlayerFromCharacter(ray.Instance.Parent) then
			ray.Instance.Parent.Humanoid.Health -= 5
			print("Damaged Someone")
		end
		
		current += math.abs(angle)*2 / castAmount
	end
end

while wait(2) do
	rayFunction(35, 20)
end

And here is the result:
image

For the example I just created parts at the end of the ray, and it works great for detecting players within an angle.

I had also tried other solutions in a 3d cone, but ultimately they were very performance costly, and this is runs very smoothly when put in a while wait() do loop.

Thanks for sending me a link to the other page as it helped me research other similar things.

Many Thanks.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.