Raycast not working

Raycast is not detecting instances between npc and player.

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

local npc = script.Parent

RunService.Heartbeat:Connect(function()
	for i,v in pairs(Players:GetPlayers()) do
		local player = v
		local character = v.Character
		if character then
			local dotProduct = (npc.HumanoidRootPart.Position - character.HumanoidRootPart.Position).Unit:Dot(npc.HumanoidRootPart.CFrame.LookVector)
			if math.max(dotProduct) < 0 then
				local raycastParams = RaycastParams.new()
				raycastParams.FilterDescendantsInstances = {npc, character}
				raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
				local raycastResult = game.Workspace:Raycast(npc.Head.Position, character.Head.Position, raycastParams)
				if not raycastResult then
					print(player.Name)
				end
			end
		end
	end
end)

https://gyazo.com/dea50ba9a57467f530a63910bd000a30

You are checking if the the raycast failed rather then if it succeed

yeah, if there are no obstacles then npc is seeing the player

why are you adding the player’s character to the blacklist?

i want to check only for obstacles

Your direction is the position of character.Head, while it should be the direction from the origin position. Try (npc.Head.Position - character.Head.Position).Magnitude instead

i get error

when i visualize ray with

local part = Instance.new("Part", workspace)
				part.Anchored = true
				part.CanCollide = false
				part.Color = Color3.fromRGB(255,0,0)
				part.Size = Vector3.new(0.2, 0.2, (npc.Head.Position - character.Head.Position).Magnitude)
				part.CFrame = CFrame.new((npc.Head.Position + character.Head.Position)/2, character.Head.Position)

it visualizes it correctly, but if i use raycastResult instead of character.Head.Position

local part = Instance.new("Part", workspace)
				part.Anchored = true
				part.CanCollide = false
				part.Color = Color3.fromRGB(255,0,0)
				part.Size = Vector3.new(0.2, 0.2, (npc.Head.Position - raycastResult.Position).Magnitude)
				part.CFrame = CFrame.new((npc.Head.Position + raycastResult.Position)/2, raycastResult.Position)

it gives me an error

RaycastResults don’t return an Instance, but rather a table of values.

You’re perhaps looking for RaycastResults.Instance.

so it turns out that raycastResult is nil

Are you still checking if raycastResult is nil? If you are, you’re ignoring the valid RaycastResults that actually has the .Instance value. You should probably do this:

if raycastResults then -- Check if a hit is found.
	if raycastResults.Instance:IsDescendantOf(character) then -- If the part hit is inside the Character
		print(player.Name)
	end
end

i want to check if there is an obstacle between npc and player, shouldnt the condition be if not raycastResult.Instance then?

No. RaycastResults is only given if there is a successful hit that is not part of the blacklist (or when using whitelist, only specific parts included.)

If your ray points at the sky, you get no RaycastResults. You point on a part however, you’ll get a RaycastResults, depending on your blacklist/whitelist. If RaycastResults is nil, you can’t access .Instance, because nil.Instance doesn’t exist.

The better way to detect obstacles is by determining whether or not the Instance that was hit is either an obstacle, or a Player. Therefore, if the part that was detected is anything but like a LeftUpperLeg or Right Arm, we know that part is an obstacle, otherwise the part that was detected belongs to the Player’s character.

but character, which means all characters cause of loop, is already blacklisted, therefore everything that isnt a players’ characters should be ignored, doesnt it?

also this proves that raycast is being cast wrong:
https://gyazo.com/09fbcfa75aea6580e22edb5e0a402571
(i did this btw

if raycastResult then
     print("hit")
end

)

Try printing the name of the part that gets detected by the ray. What are the names that pop up in the output?

if raycastResult then
     print(raycastResult.Instance.Name)
end

image
the wall
image
it is the only instance with name “Obstacle” btw

ive discovered something, wait a sec i need gyazo

https://gyazo.com/1c9a26d6a6043a757fbe27c92d3669cb

if raycastResult then
	local part = Instance.new("Part", workspace)
	part.Anchored = true
	part.CanCollide = false
	part.Color = Color3.fromRGB(255,0,0)
	part.Size = Vector3.new(0.1, 0.1, (npc.Head.Position - raycastResult.Position).Magnitude)
	part.CFrame = CFrame.new((npc.Head.Position + raycastResult.Position)/2, raycastResult.Position)
end

I rechecked your code, and found out that your Raycast() function has two positional Vector3’s instead of one positional Vector3 and one directional Vector3 (mutliplied to a certain number, acting as the Distance.

I rewrote parts of your script so that the ray actually hits the player’s head.

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

local npc = script.Parent

RunService.Heartbeat:Connect(function()
	for i,v in pairs(Players:GetPlayers()) do
		local player = v
		local character = v.Character
		if character then
			local facingVector : Vector3 = (npc.HumanoidRootPart.Position - character.HumanoidRootPart.Position)
			local unitFacingVector = facingVector.Unit
			local dotProduct = unitFacingVector:Dot(npc.HumanoidRootPart.CFrame.LookVector)
			print(dotProduct)
			if math.max(dotProduct) < 0 then
				local cframeAngle = CFrame.lookAt(npc.HumanoidRootPart.Position, character.HumanoidRootPart.Position):Inverse().LookVector * Vector3.new(-1, -1, 1)
				local raycastParams = RaycastParams.new()
				
				raycastParams.FilterDescendantsInstances = {npc} -- removed player's character
				raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
				local raycastResult = game.Workspace:Raycast(npc.Head.Position, cframeAngle * 90, raycastParams) -- facingVector * 30 is the Direction vector. multiplied by 30 for distance. 
				
				if raycastResult then
					if raycastResult.Instance:IsDescendantOf(character) then
						print(player.Name, "found")
					end
				end
			end
		end
	end
end)

works really well but, why :Inverse() and Vector3.new(-1, -1, -1)? i am newbie, never used :Inverse() before.

1 Like