Need help with Raycasting

I have an NPC that when an object is in between the NPC and the Target, the NPC will use Pathfinding to get to the target, however if there is no objects in the way the NPC will use basic MoveTo() to get the to target

The problem is, when the NPC gets too close to the target, the Ray will go through the target making the NPC use pathfinding which causes this:

BLUE = MoveTo() RED = Pathfinding

code:



local npc = script.Parent
local human = npc.Humanoid
local hrp = npc:WaitForChild("HumanoidRootPart")

local PFS = game:GetService("PathfindingService")
local RUNSERVICE = game:GetService("RunService")

local RaycastHitbox = require(game:GetService("ReplicatedStorage").RaycastHitboxV4)
local Params = RaycastParams.new()
Params.FilterType = Enum.RaycastFilterType.Blacklist
Params.FilterDescendantsInstances = {npc} 

local newHitbox = RaycastHitbox.new(script.Parent.Knife)
newHitbox.RaycastParams = Params
RaycastHitbox.DetectionMode = 1
--task.wait()


local AttackCooldown = .75
local HitDebounce = false
local AttackDebounce = false
local MaxAttackDistance = 3

local SwingSounds = npc.AttackZone.SwingSounds:GetChildren()
local HitSounds = npc.AttackZone.HitSounds:GetChildren()

local destination = workspace.CampingPath:GetChildren()

local IsAttacking = npc.IsAttacking

local foundtarget = nil

local SpawnIdle = human.Animator:LoadAnimation(script.Parent.SpawnIdle)
local SpawnAnim = human.Animator:LoadAnimation(script.Parent.Spawn)

--SpawnIdle:Play()

workspace.Values.EnableCamping.Changed:Wait()
print("CAMPING MONSTER ENABLED")
--SpawnIdle:Stop()
--SpawnAnim:Play()

--SpawnAnim.Stopped:Wait()
--[[
newHitbox.OnHit:Connect(function(hit, humanoid, hum) 
	if HitDebounce == false then
		HitDebounce = true
		local RandomHitSound = HitSounds[math.random(1, #HitSounds)]
		print(humanoid)
		RandomHitSound:Play()
		humanoid:TakeDamage(10)
		print("hit")
		newHitbox:HitStop()
		task.wait(AttackCooldown)
		HitDebounce = false
	end
end)	
--]]

local Attack1Anim = human.Animator:LoadAnimation(script.Parent.Attack)
local Attack2Anim = human.Animator:LoadAnimation(script.Parent.Attack2)
local WalkAnim = human.Animator:LoadAnimation(script.Parent.Walk)
local RunAnim = human.Animator:LoadAnimation(script.Parent.Run)

local SpeedTween = game:GetService("TweenService"):Create(human, TweenInfo.new(2.5), {WalkSpeed = 20})


human.Running:Connect(function(speed)
	if speed > 15 then
		RunAnim:Play()
		WalkAnim:Stop()
	elseif speed < 10 then
		WalkAnim:Play()
		RunAnim:Stop()
	end
end)

Attack1Anim.Stopped:Connect(function()
	newHitbox:HitStop()
end)
Attack2Anim.Stopped:Connect(function()
	newHitbox:HitStop()
end)

npc.PrimaryPart:SetNetworkOwner(nil)


local points = {}
for _,part in ipairs(destination) do
	table.insert(points,part)
	task.wait()
end

local walkDebounce = false

function walkRandomly()
if walkDebounce == false and foundtarget == nil then
walkDebounce = true
print(walkDebounce)
	--IsAttacking.Value = false
	local point = points[math.random(1,#points)]
	--local target = FindTarget()
	local path = game:GetService("PathfindingService"):CreatePath({
		AgentRadius = 2,
		AgentHeight = 5,
		AgentCanJump = true,
		Costs = {
			PathFindingModifier = math.huge
		}
	})
	path.Blocked:Connect(function()
		path:Destroy()
		print("DEBUG: PATH BLOCKED (WALKRANDOMLY)")
		walkRandomly()
	end)
	path:ComputeAsync(hrp.Position, point.Position)

	local waypoints = path:GetWaypoints()
	for _, waypoint in ipairs(waypoints) do
		if foundtarget == nil then
			--print("DEBUG: WALKING RANDOMLY TO WAYPOINT")
			--IsAttacking.Value = false
			human:MoveTo(waypoint.Position)
			IsAttacking.Value = false
			foundtarget = nil
			human.WalkSpeed = 8
			path.Blocked:Connect(function()
				path:Destroy()
				print("DEBUG: PATH BLOCKED (WALKRANDOMLY)")
				walkRandomly()
			end)
			if waypoint.Action == Enum.PathWaypointAction.Jump then
				human:ChangeState(Enum.HumanoidStateType.Jumping)
			end
		end
		if IsAttacking.Value or foundtarget == 1 then path:Destroy() break end
		human.MoveToFinished:Wait()
		--FindTarget()
	end

	if path.Status == Enum.PathStatus.Success and foundtarget == nil then
		print('Success!')
		walkDebounce = false
	end
	end
end


local Swings = 0

local function findTarget()
	--print('should run every frame 2')
	local players = game:GetService("Players"):GetPlayers()
	local nearesttarget
	local maxDistance = 25 -- distance
	for i,player in pairs(players) do
		if player.Character then
			local target = player.Character
			if target.Humanoid.Health > 0 then
			local distance = (npc.HumanoidRootPart.Position - target:WaitForChild("HumanoidRootPart").Position).Magnitude
			if distance < maxDistance  then
				nearesttarget = target
				maxDistance = distance
				--print(target)
				--print("Found target, nearesttarget = target")
			end
			task.spawn(function()
			local humanoid = target.Humanoid
			if distance <= MaxAttackDistance and not AttackDebounce then
				--
				AttackDebounce = true
				if Swings == 0 then
				Attack1Anim:Play()
				Swings += 1
				else
					Attack2Anim:Play()
					Swings = 0
				end
				--newHitbox:HitStart()
				local RandomSwingSound = SwingSounds[math.random(1, #SwingSounds)]
				RandomSwingSound:Play()
				if HitDebounce == false then
					HitDebounce = true
					local RandomHitSound = HitSounds[math.random(1, #HitSounds)]
					print(humanoid)
					RandomHitSound:Play()
					--humanoid:TakeDamage(10)
					print("hit")
					--newHitbox:HitStop()
					task.wait(AttackCooldown)
					HitDebounce = false
				end
				task.wait(AttackCooldown)
				AttackDebounce = false--
			end
			end)
			
		end
		end
		end
	return nearesttarget
end

local function getPath(destination)
	local path = PFS:CreatePath()

	path:ComputeAsync(npc.HumanoidRootPart.Position, destination)

	return path
end
local function CheckRaycast()
	local target = findTarget()
	if target then
		local ray = Ray.new(npc.HumanoidRootPart.Position,(target.HumanoidRootPart.Position - npc.HumanoidRootPart.Position).unit * 100) -- create the ray
		local hit,pos = workspace:FindPartOnRay(ray,npc) -- find parts that the ray hit
		if hit then -- if the ray hit a part then
			--[[
			local distance = (npc.HumanoidRootPart.Position - pos).Magnitude
			local p = Instance.new("Part")
			p.Anchored = true
			p.CanCollide = false
			p.Size = Vector3.new(1.1, 1.1, distance)
			p.CFrame = CFrame.lookAt(pos, npc.HumanoidRootPart.Position)*CFrame.new(0, 0, -distance/2)
			p.Parent = workspace
			--]]
			if hit:IsDescendantOf(target) then -- if the part is part of the target's character then
				--foundtarget = 1
				return true -- return true
			end
		end
		--IsAttacking.Value = false
		--foundtarget = nil
		return false -- if no target was found, return false
	end
end


local function pathFindTo(destination)
	local path = getPath(destination)
	local target = findTarget()


	path.Blocked:Connect(function()
		path:Destroy()
	end)


if target and target.Humanoid.Health > 0 then
	for i,waypoint in pairs(path:GetWaypoints()) do

		if waypoint.Action == Enum.PathWaypointAction.Jump then
			human.Jump = true
		end
		IsAttacking.Value = true
		foundtarget = 1
		human.WalkSpeed = 18
		if CheckRaycast() == false then
			npc.Highlight.FillColor = Color3.fromRGB(255, 0, 0)
			--print("Using Pathfinding, Should just be this printing")
		human:MoveTo(waypoint.Position)
		human.MoveToFinished:Wait()
		else
			npc.Highlight.FillColor = Color3.fromRGB(0, 0, 255)
			human:MoveTo(target.PrimaryPart.Position)
			task.wait()
			--print("Using Basic MoveTo(), Should just be this printing")
		end
--[[
if CheckRaycast() == true then -- you're going to have to make your own checkraycast function
	repeat
		human:MoveTo(target.PrimaryPart.Position)
		task.wait()
		print("Using Basic MoveTo(), Should just be this printing")
	until CheckRaycast() == false
	break
end
--]]
	end
end
end




while true do
	task.wait()
	--print('every frame bruh')
	local target = findTarget()
	task.spawn(function()
		if target then
			--print("Attacking"..target.Name)
			--print('attackin')
			pathFindTo(target:WaitForChild("HumanoidRootPart").Position)
		else
			--print('walking')
			walkRandomly()
		end

	end)
	
	CheckRaycast()	
end
2 Likes

My first thoughts are to try using workspace:Raycast(…) with Raycast params that only whitelist players. This way you can start the ray further back without it triggering on the npc itself.

1 Like

you think workspace:Raycast instead of the Ray.new that i use? why would i only whitelist players?

couldnt I just use the same code but for i make the ray slightly further back than the HRP?

could you possibly provide a code example?

You are already whitelisting for players using if statements on the hit object. I.e. if hit is not part of a character then that is the same result as hit being nil. You can reproduce this behaviour by using Raycast params which just whitelist that players character.

workspace:Raycast() replaces workspace:FindPartOnRay().

The origin of your ray is currently npc.HumanoidRootPart.Position . What I would suggest is something like this:

local npcPos = npc.HumanoidRootPart.Position
local targetPos = target.HumanoidRootPart.Position

local offset = 4
local rayDistance = 100

local direction  = (targetPos - npcPos).unit
local origin = npcPos - offset * direction

local rayResult = workspace:Raycast(origin, (rayDistance + offset) * direction)

seems like the ray fired wrong, and the NPC is always using pathfinding because of that

local function CheckRaycast()
	local target = findTarget()
	if target then
		local npcPos = npc.HumanoidRootPart.Position
		local targetPos = target.HumanoidRootPart.Position

		local offset = 4
		local rayDistance = 100

		local direction  = (targetPos - npcPos).unit
		local origin = npcPos - offset * direction

		local rayResult = workspace:Raycast(origin, (rayDistance + offset) * direction)
		--local ray = Ray.new(npc.HumanoidRootPart.Position,(target.HumanoidRootPart.Position - npc.HumanoidRootPart.Position).unit * 100) -- create the ray
		--local hit,pos = workspace:FindPartOnRay(ray,npc) -- find parts that the ray hit
		if rayResult.Instance then -- if the ray hit a part then
			--[[
			local distance = (npc.HumanoidRootPart.Position - pos).Magnitude
			local p = Instance.new("Part")
			p.Anchored = true
			p.CanCollide = false
			p.Size = Vector3.new(1.1, 1.1, distance)
			p.CFrame = CFrame.lookAt(pos, npc.HumanoidRootPart.Position)*CFrame.new(0, 0, -distance/2)
			p.Parent = workspace
			--]]
			if rayResult.Instance:IsDescendantOf(target) then -- if the part is part of the target's character then  TARGET IS IN DIRECT PATH
				--foundtarget = 1
				return true -- return true
			end
		end
		--IsAttacking.Value = false
		--foundtarget = nil
		return false -- if no target was found, return false  TARGET BEHIND OBJECT
	end
end

also, why does the npc even turn back while using pathfinding, is there a problem with the full code?

I think you still need to include the raycast params in this. I.e.


-- Keep a reference in an enclosing scope so that the same params object can be reused
local checkParams = RaycastParams.new()
checkParams.FilterType = Enum.RaycastFilterType.Whitelist

local function CheckRaycast()
	local target = findTarget()

	if not target then return false end
	
	checkParams.FilterDescendantsInstances = {target} -- whitelist the target character only
	local npcPos = npc.HumanoidRootPart.Position
	local targetPos = target.HumanoidRootPart.Position
	local offset = 4
	local rayDistance = 100

	local direction  = (targetPos - npcPos).unit
	local origin = npcPos - offset * direction

	local rayResult = workspace:Raycast(origin, (rayDistance + offset) * direction, checkParams)
	
	if not rayResult.Instance or not rayResult.Instance:IsDescendantOf(target) then 
		return false 
	end

	return true -- return true
end

i found out that the issue is literally the params, since it only checks the target i cant detect if it doesnt hit the target to use pathfinding instead.
but if i remove the params the ray just doesnt work and the npc just kinda breaks @McThor2

local function CheckRaycast()
	local target = findTarget()

	if not target then return false end

	checkParams.FilterDescendantsInstances = {target} -- whitelist the target character only
	local npcPos = npc.HumanoidRootPart.Position
	local targetPos = target.HumanoidRootPart.Position
	local offset = 4
	local rayDistance = 100

	local direction  = (targetPos - npcPos).unit
	local origin = npcPos - offset * direction 

	local rayResult = workspace:Raycast(origin, (rayDistance + offset) * direction)--, checkParams)
	local distance = (origin - rayResult.Instance.Position).Magnitude
	local p = Instance.new("Part")
	p.Anchored = true
	p.CanCollide = false
	p.Size = Vector3.new(0.1, 0.1, distance)
	p.CFrame = CFrame.new(origin, rayResult.Instance.Position)*CFrame.new(0, 0, -distance/2)
	p.Parent = workspace
	--print(rayResult.Instance)
	if rayResult.Instance then
		
		
	if rayResult.Instance:IsDescendantOf(target) then 
		--print("true")
		return true 
		
	end
	end
	print(rayResult.Instance)
	print('false')
	return false -- return false

end

You could use one ray for knife damage and another ray for movement from HumanoidRootPart.

the knife damage is fine, the problem is the raycast to find the player is not working.

so when the npc is chasing the player and the ray hits the player, the npc should use MoveTo() to get to the player, but if the npc is chasing a player and the player is behind a wall (or the ray hits something else than the player) the npc should use pathfinding

however this isnt working because

i also posted the function for checking the raycast.

more info:
the ray hits perfectly when

but

@F0xBirdmansBFF the raycast params are using whitelist. whitelisting objects makes them the only objects the ray will hit try setting the filter type to blacklist. I am pretty sure that the cause of it breaking with no params is the fact that the raycast goes farther than the player. try subtracting the npc’s position from the player’s position for the direction of the ray cast.

1 Like

so

local direction  = (npcPos - targetPos).unit

why would i need to blacklist anything?

local function CheckRaycast()
	local target = findTarget()

	if not target then return false end

	checkParams.FilterDescendantsInstances = {target} -- whitelist the target character only
	local npcPos = npc.HumanoidRootPart.Position
	local targetPos = target.HumanoidRootPart.Position
	local offset = 4
	local rayDistance = 100

	local direction  = (npcPos - targetPos).unit
	local origin = npcPos - offset * direction 

	local rayResult = workspace:Raycast(origin, (rayDistance + offset) * direction)--, checkParams)
	local distance = (origin - rayResult.Instance.Position).Magnitude
	local p = Instance.new("Part")
	p.Anchored = true
	p.CanCollide = false
	p.Size = Vector3.new(0.1, 0.1, distance)
	p.CFrame = CFrame.new(origin, rayResult.Instance.Position)*CFrame.new(0, 0, -distance/2)
	p.Parent = workspace
	--print(rayResult.Instance)
	if rayResult.Instance then
		
		
	if rayResult.Instance:IsDescendantOf(target) then 
		--print("true")
		return true 
		
	end
	end
	print(rayResult.Instance)
	print('false')
	return false -- return false

end

this happens:


(parts are the raycast)

you are saying that when the npc gets close to the player it switches to pathfinding right? and you shouldn’y need to unit it the ray will go from the npc to the player and not any further.

no, when the player goes behind something or something is in the way, thats when the npc should use pathfinding, otherwise if there is nothing in the way it uses moveto

that is why the npc should blacklist the player. because you want the raycast to hit the wall and not the player. whitelisting it makes the ray only hit the player.

this is how the raycast should work: it fired from the NPC, and if it hits the player, that means its in a direct path of the player, so use MoveTo()
if the ray doesnt hit the player, that means its not in a direct path of the player, so use pathfinding instead.
i dont want any params on it because that just removes the point of the ray in the first place

if the raycast can only hit the player it will not detect anything in the path. try checking for obstacles in between the npc and the player instead.

the ray will not need to hit the player as it will end at the player. also for the raycast method I was talking about earlier to work you will need to either raycast from the npcs position or subtract the origin from the players position instead.

this is what ive been saying, and the only way to check for obstacles while checking for playing is removing the params like ive been saying, but when i remove params it just breaks.

tried this already, although ill post the function im using (if you want the full script ask)

local function CheckRaycast()
	local target = findTarget()

	if not target then return false end

	checkParams.FilterDescendantsInstances = {npc} -- whitelist the target character only
	local npcPos = npc.HumanoidRootPart.Position
	local targetPos = target.HumanoidRootPart.Position
	local offset = 4
	local rayDistance = 100

	local direction  = (npcPos - targetPos)
	local origin = npcPos - offset * direction 

	local rayResult = workspace:Raycast(origin, (rayDistance + offset) * direction, checkParams)
	local distance = (origin - rayResult.Instance.Position).Magnitude
	local p = Instance.new("Part")
	p.Anchored = true
	p.CanCollide = false
	p.Size = Vector3.new(0.1, 0.1, distance)
	p.CFrame = CFrame.new(origin, rayResult.Instance.Position)*CFrame.new(0, 0, -distance/2)
	p.Parent = workspace
	--print(rayResult.Instance)
	if rayResult.Instance then
		
		
	if rayResult.Instance:IsDescendantOf(target) then 
		--print("true")
		return true 
		
	end
	end
	print(rayResult.Instance)
	print('false')
	return false -- return false

end

if you set the whitelist to blacklist it will check for everything except the player. try setting the raycastresult to workspace:Raycast(npcPos, direction, checkParams)

made local distance error
here is the full code:



local npc = script.Parent
local human = npc.Humanoid
local hrp = npc:WaitForChild("HumanoidRootPart")

local PFS = game:GetService("PathfindingService")
local RUNSERVICE = game:GetService("RunService")

local RaycastHitbox = require(game:GetService("ReplicatedStorage").RaycastHitboxV4)
local Params = RaycastParams.new()
Params.FilterType = Enum.RaycastFilterType.Blacklist
Params.FilterDescendantsInstances = {npc} 

local newHitbox = RaycastHitbox.new(script.Parent.Knife)
newHitbox.RaycastParams = Params
RaycastHitbox.DetectionMode = 1
--task.wait()


local AttackCooldown = .75
local HitDebounce = false
local AttackDebounce = false
local MaxAttackDistance = 3

local SwingSounds = npc.AttackZone.SwingSounds:GetChildren()
local HitSounds = npc.AttackZone.HitSounds:GetChildren()

local destination = workspace.CampingPath:GetChildren()

local IsAttacking = npc.IsAttacking

local foundtarget = nil

local SpawnIdle = human.Animator:LoadAnimation(script.Parent.SpawnIdle)
local SpawnAnim = human.Animator:LoadAnimation(script.Parent.Spawn)


npc.Humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)
npc.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Ragdoll, false)
npc.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Seated, false)
npc.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Swimming, false)
npc.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Dead, false)
npc.Humanoid:SetStateEnabled(Enum.HumanoidStateType.StrafingNoPhysics, false)
npc.Humanoid:SetStateEnabled(Enum.HumanoidStateType.FallingDown, false)
npc.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Flying, false)

--SpawnIdle:Play()

workspace.Values.EnableCamping.Changed:Wait()
print("CAMPING MONSTER ENABLED")
--SpawnIdle:Stop()
--SpawnAnim:Play()

--SpawnAnim.Stopped:Wait()
--[[
newHitbox.OnHit:Connect(function(hit, humanoid, hum) 
	if HitDebounce == false then
		HitDebounce = true
		local RandomHitSound = HitSounds[math.random(1, #HitSounds)]
		print(humanoid)
		RandomHitSound:Play()
		humanoid:TakeDamage(10)
		print("hit")
		newHitbox:HitStop()
		task.wait(AttackCooldown)
		HitDebounce = false
	end
end)	
--]]

local Attack1Anim = human.Animator:LoadAnimation(script.Parent.Attack)
local Attack2Anim = human.Animator:LoadAnimation(script.Parent.Attack2)
local WalkAnim = human.Animator:LoadAnimation(script.Parent.Walk)
local RunAnim = human.Animator:LoadAnimation(script.Parent.Run)

local SpeedTween = game:GetService("TweenService"):Create(human, TweenInfo.new(2.5), {WalkSpeed = 20})


human.Running:Connect(function(speed)
	if speed > 15 then
		RunAnim:Play(1)
		WalkAnim:Stop()
	elseif speed < 10 then
		WalkAnim:Play(1)
		RunAnim:Stop()
	end
end)

Attack1Anim.Stopped:Connect(function()
	newHitbox:HitStop()
end)
Attack2Anim.Stopped:Connect(function()
	newHitbox:HitStop()
end)

npc.PrimaryPart:SetNetworkOwner(nil)


local points = {}
for _,part in ipairs(destination) do
	table.insert(points,part)
	task.wait()
end

local walkDebounce = false

local function walkRandomly()
	if walkDebounce == false and foundtarget == nil then
		walkDebounce = true
		print('walk debounce false, and foundtarget is also false!!!')
		print(walkDebounce)
		--IsAttacking.Value = false
		local point = points[math.random(1,#points)]
		--local target = FindTarget()
		local path = game:GetService("PathfindingService"):CreatePath({
			AgentRadius = 2,
			AgentHeight = 5,
			AgentCanJump = true,
			Costs = {
				PathFindingModifier = math.huge
			}
		})
		print("point chosen")
		path.Blocked:Connect(function()
			path:Destroy()
			print("DEBUG: PATH BLOCKED (WALKRANDOMLY)")
			walkRandomly()
		end)
		path:ComputeAsync(hrp.Position, point.Position)

		local waypoints = path:GetWaypoints()
		for _, waypoint in ipairs(waypoints) do
			if foundtarget == nil then
				print("For _, waypoint")
				--print("DEBUG: WALKING RANDOMLY TO WAYPOINT")
				--IsAttacking.Value = false
				human:MoveTo(waypoint.Position)
				IsAttacking.Value = false
				foundtarget = nil
				human.WalkSpeed = 8
				path.Blocked:Connect(function()
					path:Destroy()
					print("DEBUG: PATH BLOCKED (WALKRANDOMLY)")
					walkRandomly()
				end)
				if waypoint.Action == Enum.PathWaypointAction.Jump then
					human:ChangeState(Enum.HumanoidStateType.Jumping)
				end
			end
			if IsAttacking.Value or foundtarget == 1 then path:Destroy() break end
			human.MoveToFinished:Wait()
			--FindTarget()
		end

		if path.Status == Enum.PathStatus.Success and foundtarget == nil then
			print('Success!')
			walkDebounce = false
		end
	end
end


local Swings = 0

local function findTarget()
	--print('should run every frame 2')
	local players = game:GetService("Players"):GetPlayers()
	local nearesttarget
	local maxDistance = 25 -- distance
	for i,player in pairs(players) do
		if player.Character then
			local target = player.Character
			if target.Humanoid.Health > 0 then
			local distance = (npc.HumanoidRootPart.Position - target:WaitForChild("HumanoidRootPart").Position).Magnitude
			if distance < maxDistance  then
				nearesttarget = target
				maxDistance = distance
				--print(target)
				--print("Found target, nearesttarget = target")
			else
				--print("Lost target")
				nearesttarget = nil
				foundtarget = nil
			end
			local humanoid = target.Humanoid
			if distance <= MaxAttackDistance and not AttackDebounce then
				--
				AttackDebounce = true
				if Swings == 0 then
				Attack1Anim:Play()
				Swings += 1
				else
					Attack2Anim:Play()
					Swings = 0
				end
				--newHitbox:HitStart()
				local RandomSwingSound = SwingSounds[math.random(1, #SwingSounds)]
				RandomSwingSound:Play()
				if HitDebounce == false then
					HitDebounce = true
					local RandomHitSound = HitSounds[math.random(1, #HitSounds)]
					print(humanoid)
					RandomHitSound:Play()
					--humanoid:TakeDamage(10)
					print("hit")
					--newHitbox:HitStop()
					task.wait(AttackCooldown)
					HitDebounce = false
				end
				task.wait(AttackCooldown)
				AttackDebounce = false--
			end
			
		end
		end
		end
	return nearesttarget
end

local function getPath(destination)
	local path = PFS:CreatePath()

	path:ComputeAsync(npc.HumanoidRootPart.Position, destination)
	print("getPath function called, path computed to waypoint")

	return path
end

-- Keep a reference in an enclosing scope so that the same params object can be reused
local checkParams = RaycastParams.new()
checkParams.FilterType = Enum.RaycastFilterType.Blacklist

local function CheckRaycast()
	local target = findTarget()

	if not target then return false end

	checkParams.FilterDescendantsInstances = {npc} -- whitelist the target character only
	local npcPos = npc.HumanoidRootPart.Position
	local targetPos = target.HumanoidRootPart.Position
	local offset = 4
	local rayDistance = 100

	local direction  = (npcPos - targetPos)
	local origin = npcPos - offset * direction 

	local rayResult = workspace:Raycast(origin, (rayDistance + offset) * direction, checkParams)
	local distance = (origin - rayResult.Instance.Position).Magnitude
	local p = Instance.new("Part")
	p.Anchored = true
	p.CanCollide = false
	p.Size = Vector3.new(0.1, 0.1, distance)
	p.CFrame = CFrame.new(origin, rayResult.Instance.Position)*CFrame.new(0, 0, -distance/2)
	p.Parent = workspace
	--print(rayResult.Instance)
	if rayResult.Instance then
		
		
	if rayResult.Instance:IsDescendantOf(target) then 
		--print("true")
		return true 
		
	end
	end
	print(rayResult.Instance)
	print('false')
	return false -- return false

end

local function pathFindTo(destination)
	--local path = getPath(destination)
	local target = findTarget()
	CheckRaycast()




if target and target.Humanoid.Health > 0 then
	IsAttacking.Value = true
	foundtarget = 1
	human.WalkSpeed = 10
	if CheckRaycast() == true then
		npc.Highlight.FillColor = Color3.fromRGB(0, 0, 255)
		human:MoveTo(target.PrimaryPart.Position)
		task.wait()
		--print("Using Basic MoveTo(), Should just be this printing")
	end
	
	if CheckRaycast() == false then
		print('raycast false')
		local path = getPath(destination)
		path.Blocked:Connect(function()
			path:Destroy()
		end)
	for i,waypoint in pairs(path:GetWaypoints()) do

		if waypoint.Action == Enum.PathWaypointAction.Jump then
			human.Jump = true
		end
			npc.Highlight.FillColor = Color3.fromRGB(255, 0, 0)
			print("Using Pathfinding, Should just be this printing")
		human:MoveTo(waypoint.Position)
		human.MoveToFinished:Wait()
		end
		path.Blocked:Connect(function()
			path:Destroy()
		end)
--[[
if CheckRaycast() == true then -- you're going to have to make your own checkraycast function
	repeat
		human:MoveTo(target.PrimaryPart.Position)
		task.wait()
		print("Using Basic MoveTo(), Should just be this printing")
	until CheckRaycast() == false
	break
end
--]]
	end
end
end


while true do
	task.wait()
	--print('every frame bruh')
	local target = findTarget()
	--print(target)
	task.spawn(function()
		if target then
			--print("Attacking"..target.Name)
			--print('attackin')
			pathFindTo(target:WaitForChild("HumanoidRootPart").Position)
		else
			--print('walking')
			walkRandomly()
		end

	end)
	
	--CheckRaycast()	
end