Need help with NPC view cone positioning

,

I’m currently working on a view cone system for my game enemies. I’m having trouble calculating the X and Y position of each ray cast target point. I’ve tried multiple equations but almost always end up with a circle of parts around the origin.

The code should take an origin part, a radius, and an angle. It should generate a set amount of ray target positions within the angle from the part’s look vector. My most recent code looks like this:

local radius = 30
local angle = 30
local rayCount = angle/2

for i = 1,rayCount,1 do
	local angle = i * (((math.pi * radius * angle) / 180) / rayCount)
	local x = orininPart.Position.X + (radius * math.cos(angle))
	local z = orininPart.Position.Z + (radius * math.sin(angle))
	
	local targetPosition: Vector3 = (Vector3.new(x,0,z))
	--local targetPosition: Vector3 = (orininPart.CFrame * CFrame.new(x,0,y)).Position		
	--local raycast = workspace:Raycast(orininPart.Position,(targetPosition - orininPart.Position).Unit * radius,castData.rayParams or RAY_PARAMS)

	--visualizeCast(raycast,orininPart.Position,targetPosition)
	Utility:CreateObject("Part",{
		Color = Color3.fromRGB(255, 0, 0),
		Anchored = true,
		CanCollide = false,
		CanQuery = false,
		CanTouch = false,
		CastShadow = false,
		Material = Enum.Material.Neon,
		Size = Vector3.new(1,1,1),
		Position = targetPosition,
		Parent = workspace
	})
end

Right now I’m simply making a part at the position for proof of concept. An amazing drawing of the ideal result:

If any math people have a solution that would be awesome, thanks.

This should work. I get it’s been two years but this may help anyone else trying this same thing.

local head = workspace.Target.Head

local radius = 60
local angle = 60
local rayCount = angle

for i = -rayCount/2,rayCount/2,1 do
		local angle = math.rad(-90) + i * ((angle / radius) / rayCount)
		local x = (radius * math.cos(angle))
		local z = (radius * math.sin(angle))
		
		local targetCF = (head.CFrame * CFrame.new(x,0,z))
		
		local rayparams = RaycastParams.new()
		rayparams.FilterDescendantsInstances = {character}
		rayparams.FilterType = Enum.RaycastFilterType.Blacklist
		
		local ray = workspace:Raycast(head.Position, targetCF.Position - head.Position, rayparams)
		
		if ray then
			local Part = Instance.new("Part")
			Part.Color = Color3.fromRGB(255, 255, 255)
			Part.Transparency = 0.99
			Part.Anchored = true
			Part.CanCollide = false
			Part.CanQuery = false
			Part.CanTouch = false
			Part.CastShadow = false
			Part.Material = Enum.Material.Neon
			Part.Size = Vector3.new(1,4, (head.Position-ray.Position).Magnitude)
			Part.CFrame = CFrame.lookAt(head.Position, ray.Position) * CFrame.new(0,0,-(head.Position-ray.Position).Magnitude/2)
			Part.Parent = character
			Part.Massless = true
		else
			local Part = Instance.new("Part")
			Part.Color = Color3.fromRGB(255, 255, 255)
			Part.Transparency = 0.99
			Part.Anchored = true
			Part.CanCollide = false
			Part.CanQuery = false
			Part.CanTouch = false
			Part.CastShadow = false
			Part.Material = Enum.Material.Neon
			Part.Size = Vector3.new(1,4, (head.Position-targetCF.Position).Magnitude)
			Part.CFrame = CFrame.lookAt(head.Position, targetCF.Position) * CFrame.new(0,0,-(head.Position-targetCF.Position).Magnitude/2)
			Part.Parent = character
			Part.Massless = true
		end
	end
2 Likes