How do i get these blocks to rotate with the character? (raycasting)

So basically, i am trying to give this NPC vision that uses 5 rays cast from the head. But the rays don’t cast how i wanted them to. The issue is that the raycasts are always lined up in 1 axis. Which is an issue. Its a hard to explain, so instead i have these images to explain for me.

How do i go from this?

To this?

Some help to get it to end up like the second image will be very much appreciated.

local AiViewDistance = 100 -- How far the NPC can see.

local AiCharacter = script.Parent
local AiHead = AiCharacter:WaitForChild("Head")
local AiHRP = AiCharacter:WaitForChild("HumanoidRootPart")
local AiHum = AiCharacter:WaitForChild("Humanoid")

local Players = game:GetService("Players")

local DebugEnabled = true

local DebugBlock = Instance.new("Part")
DebugBlock.Size = Vector3.new(0.5, 0.5, 0.5)
DebugBlock.Anchored = true
DebugBlock.CanCollide = false
DebugBlock.Color = Color3.fromRGB(255, 0, 0)
DebugBlock.Name = "AiDebugPart"
local DebugBlock2 = DebugBlock:Clone()
DebugBlock2.Name = "AiDebugPart2"
local DebugBlock3 = DebugBlock:Clone()
DebugBlock3.Name = "AiDebugPart3"
local DebugBlock4 = DebugBlock:Clone()
DebugBlock4.Name = "AiDebugPart4"
local DebugBlock5 = DebugBlock:Clone()
DebugBlock5.Name = "AiDebugPart5"

function ManageRay(ray, DebuggingPart)
	local hitPart = ray.Instance
	if hitPart then  
		for _, player in pairs(Players:GetPlayers()) do -- We're going to loop through all players to see if the npc sees any of them.
			if player.Character and player.Character:IsAncestorOf(hitPart) then 
				-- Handle what happens here. 
				print("I see " .. player.Name)
			end
		end
	end 
	if DebugEnabled and ray and DebuggingPart then
		DebuggingPart.Parent = workspace
		DebuggingPart.Position = ray.Position
	end
end

while true do
	
	wait()
	
	local rayOrigin = AiHead.Position
	local ray1Direction = (AiHead.CFrame.lookVector + Vector3.new(0.5, 0, 0)) * AiViewDistance
	local ray2Direction = (AiHead.CFrame.lookVector + Vector3.new(0.25, 0, 0)) * AiViewDistance
	local ray3Direction = AiHead.CFrame.lookVector * AiViewDistance
	local ray4Direction = (AiHead.CFrame.lookVector + Vector3.new(-0.25, 0, 0)) * AiViewDistance
	local ray5Direction = (AiHead.CFrame.lookVector + Vector3.new(-0.5, 0, 0)) * AiViewDistance
	
	local raycastParams = RaycastParams.new()
	raycastParams.FilterDescendantsInstances = {AiCharacter, DebugBlock, DebugBlock2, DebugBlock3, DebugBlock4, DebugBlock5}
	raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
	
	local ray1 = workspace:Raycast(rayOrigin, ray1Direction, raycastParams)
	local ray2 = workspace:Raycast(rayOrigin, ray2Direction, raycastParams)
	local ray3 = workspace:Raycast(rayOrigin, ray3Direction, raycastParams)
	local ray4 = workspace:Raycast(rayOrigin, ray4Direction, raycastParams)
	local ray5 = workspace:Raycast(rayOrigin, ray5Direction, raycastParams)
	
	if ray1 then
		ManageRay(ray1, DebugBlock)
	end
	if ray2 then
		ManageRay(ray2, DebugBlock2)
	end
	if ray3 then
		ManageRay(ray3, DebugBlock3)
	end
	if ray4 then
		ManageRay(ray4, DebugBlock4)
	end
	if ray5 then
		ManageRay(ray5, DebugBlock5)
	end
	
end

The offset of these vectors is not relative to the initial CFrame. You’ll wanna try something like this, just play with the angles until you like them:

local ray1Direction = (AiHead.CFrame*CFrame.Angles(0,math.rad(-30),0)).LookVector * AiViewDistance
local ray2Direction = (AiHead.CFrame*CFrame.Angles(0,math.rad(-15),0)).LookVector * AiViewDistance
local ray3Direction = AiHead.CFrame.lookVector * AiViewDistance
local ray4Direction = (AiHead.CFrame*CFrame.Angles(0,math.rad(15),0)).LookVector * AiViewDistance
local ray5Direction = (AiHead.CFrame*CFrame.Angles(0,math.rad(30),0)).LookVector * AiViewDistance

Also, you could in all likelihood convert these raycast processes into a loop if you’d like to save yourself some typing.

1 Like

That is exactly what i was looking for. I know like barely anything about CFrame. Anyway, thanks!

For your ray direction values, you’re offsetting the LookVector normal of the CFrame component by a position. Vectors are petty and require a bit more reference when you work with them

Since you’re working with the CFrame components of the air AirHead, you also have a reference point to work with. You also have a point you want to offset this direction towards which luckily is enough reference to work our problem

Since you want the direction in which the reference point faces the offset point, we can use the CFrame function

CFrame:PointToObjectSpace()

In your case, we are plugging the AirHead CFrame, and our reference offset points to the function:

Direction = AirHead.CFrame:PointToObjectSpace(OffsetPoint)

This will return our vector direction from the head’s cframe to the offset points, but do note that the magnitude of the direction is not 1. For that you will have to normalize them

1 Like