Raycasting in a cone shape

  1. What do you want to achieve? Keep it simple and clear!

Im trying to get the turret model i made, to detect players in a angle in front of it, while i also want it to change later on when i add “upgrades” that increase that angle

  1. What is the issue? Include screenshots / videos if possible!

i dont know how exactly to do that, i got some code working but it detect a full 360 angle

image

this is what i want it to detect:

red area is without upgrades, blue is with upgrades

2024-02-09 21-55-50 (video showing raycast)

script im using:

wait()

local gun = script.Parent:WaitForChild("Gun")
local Main = script.Parent:WaitForChild("Main2")
--Angle = 0

function getRoots()
	local roots = {}
	for _,player in pairs(game.Players:GetChildren()) do
		--print(player)
		if player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
			table.insert(roots,player.Character.HumanoidRootPart)
			--print(player)
		end
	end
	return roots
end

position = Main.Position
radius = 30
overlapParams = OverlapParams.new()
overlapParams.FilterType = Enum.RaycastFilterType.Include
overlapParams.FilterDescendantsInstances = getRoots()

--[[
	--shooting animation
	local rotatedCFrame = CFrame.Angles(0, 0, math.rad(17))--math.rad(20))
	gun.CFrame = gun.CFrame:ToWorldSpace(rotatedCFrame)
]]
rayP = RaycastParams.new()
rayP.FilterType = Enum.RaycastFilterType.Exclude
rayP.FilterDescendantsInstances = {script.Parent,workspace.Baseplate}

local p1 = workspace:WaitForChild("p1")
local p2 = workspace:WaitForChild("p2")

while wait() do
	
	
	roots = getRoots()
	overlapParams.FilterDescendantsInstances = getRoots()
	nearbyPlayers = workspace:GetPartBoundsInRadius(position, radius, overlapParams)
	-- ^ right here, it gets a 360 area with a radius of 30
	
	
	
	for i,v in pairs(nearbyPlayers) do
		
		local direction = (Main.Position - v.Position)*-1
		p1.Position = Main.Position
		p2.Position = (Main.Position + direction)
		
		
		--print(direction)
		raycast = workspace:Raycast(Main.Position, direction,rayP)
		
		if raycast.Instance ~= nil then
			print(raycast.Instance)
		end
	end
	
	--print(nearbyPlayers[1])
	--print(gun.Rotation)
end
  1. i thought of making another ray that detect invisible barriers and then put the turret in a “box” , when the ray detects that box it shouldnt shoot but i dont think thats really practical

  2. i also thought of using a invisible cone shape and detect when a player enters it, but it might cause a lot of trouble later

it just feels like im missing something, i just dont know what it is

1 Like

Add this script inside your loop. It will detect the front so it won’t work if you try to detect from other rotation like the right or the back.

local hrp = character.HumanoidRootPart -- suposing you are detecting from here
local object -- object that you want to check if its inside the cone

local radius = 5
local angle = 45 -- to "upgrade" increase this number

if (hrp.Position - obj.Position).Magnitude <= radius then
	local dot = hrp.Position:Dot(object.Position)
	
	if dot >= 0 and dot <= math.cos(math.rad(angle)) then
		-- inside the cone
	end
end
1 Like

well like if you’re just tryna get the people within a fov boy do i have code for you (credit to sleitnick)

local function AngleBetween(VectorA, VectorB)
	return math.acos(math.clamp(VectorA:Dot(VectorB), -1, 1))
end
local function IsDotProductWithin(CFrameA, CFrameB, FOV)
	local FovCheck = math.rad(FOV) / 2

	local LookForward = CFrameA.LookVector
	local LookToPoint = (CFrameB.Position - CFrameA.Position).Unit

	local Angle = AngleBetween(LookForward, LookToPoint)

	return math.abs(Angle) <= FovCheck
end

basically do IsDotProductWithin(Turret.CFrame, Target.CFrame, 90) – set 90 the fov u want
and then raycast to the player’s position if they are within the fov

3 Likes

it didnt seem to work, i used print(“test”) and print(“inside cone”) to see where it was not working and it seems it wont activate this:

if dot >= 0 and dot <= math.cos(math.rad(angle)) then
for i,v in pairs(nearbyPlayers) do
		
		local direction = (Main.Position - v.Position)*-1
		p1.Position = Main.Position
		p2.Position = (Main.Position + direction)
		

----------------------------------------------------------------------
		local obj1 = v -- suposing you are detecting from here
		local obj2 = Main -- object that you want to check if its inside the cone

		local radius = 30
		local angle = 45 -- to "upgrade" increase this number

		if (obj1.Position - obj2.Position).Magnitude <= radius then
			print("test")
			local dot = obj1.Position:Dot(obj2.Position)
			print(dot)
			if dot >= 0 and dot <= math.cos(math.rad(angle)) then
				-- inside the cone
				print("INSIDE CONE")
			end
		end
----------------------------------------------------------------------
		--print(direction)
		raycast = workspace:Raycast(Main.Position, direction,rayP)
		
		if raycast.Instance ~= nil then
			--print(raycast.Instance)
		end
	end

edit: dot is giving me huge numbers like 1000 3000 1600 etc

Roblox has recently added generalized shapecasting, which you can use to fire a cone-shape raycast without needing to use complex math:

1 Like

it does work, but it detect the back of the turret instead of the front (using the 90 fov)

it might just be the main part that is reversed

Yup it worked! tysm i will set your post as solution

i might try using it later on the game, but still, thanks for the great info, it seems im going to need to use this later

1 Like

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