Hello! Currently I am working on an boss fight and im wondering how would you find enemies within a angle/triangle something like this
Ex: Orange is boss, Blue is angle, Pink is enemies, x’s are for not included in the count (not in angle)
I want it to find every enemy within the angle and distance but not the enemies not inside the angle, something like vision
Could dot products be a possible solution here? You could incorporate a distance check as well to determine if players are close enough in some given angle.
local function isPlayerInLineOfSight(player)
local lookDirection = rootPart.CFrame.LookVector
local directionToPlayer = (player.PrimaryPart.Position - rootPart.Position).Unit
local angle = lookDirection:Dot(directionToPlayer)
if angle < 1 then
--//Player is in line of sight
end
end
Could also adjust the maximum angle it can be, I believe anything less than 1 is in front of the NPC, and anything negative is behind it. You should be able to tighten this, and also incorporate a distance check to see if players in line of sight are also close enough.
Another thing to consider is what you want the 3D shape of the “angle” to be. Do you want “full 3D” angle, i.e. a cone shape, or do you want more of a 2D, top-down type angle, i.e. ignoring the height component for a “two planes” type of shape?
For the cone-type shape, this should work:
function vectorAngle(v1: Vector3, v2: Vector3): number
--Explanation here: https://devforum.roblox.com/t/b/208450/4
return math.acos(v1.Unit:Dot(v2.Unit))
end
function isPointInCone(point: Vector3, coneBase: Vector3, coneDir: Vector3, coneAngle: number): boolean
local baseToPoint = point - coneBase
local angle = vectorAngle(baseToPoint, coneDir)
return angle < coneAngle
end
function isPointInRange(point: Vector3, pointFrom: Vector3, maxRange: number, minRange: number?): boolean
local d = (point - pointFrom).Magnitude
return d == math.clamp(d, minRange or 0, maxRange)
end
function isPointInView(point: Vector3, view: Attachment, viewAngle: number, viewRange: number): boolean
return isPointInCone(point, view.WorldPosition, view.WorldCFrame.LookVector, viewAngle) and
isPointInRange(point, view.WorldPosition, viewRange)
end
For a two-planes-type shape you could just remove the Y component:
function isPointInBiPlaneFrustrum(
point: Vector3, plane1Point: Vector3, plane1Normal: Vector3,
plane2Point: Vector3, plane2Normal: Vector3): boolean --I swear this function name makes sense SOMEHOW https://en.wikipedia.org/wiki/Frustum
local pointToPlane1Point = plane1Point - point
local pointToPlane2Point = plane2Point - point
local rightSideOfPlane1 = pointToPlane1Point:Dot(plane1Normal) > 0
local rightSideOfPlane2 = pointToPlane2Point:Dot(plane2Normal) > 0
return rightSideOfPlane1 and rightSideOfPlane2
end
function isPointInView(point: Vector3, view: Attachment, viewAngle: number, viewRange: number)
local planeNormal1 = (view.WorldCFrame * CFrame.Angles(0, -viewAngle/2, 0)).LookVector
local planeNormal2 = (view.WorldCFrame * CFrame.Angles(0, viewAngle/2, 0)).LookVector
A.CFrame = CFrame.new(view.WorldPosition, view.WorldPosition + planeNormal1) * CFrame.new(5, 0, 0)
B.CFrame = CFrame.new(view.WorldPosition, view.WorldPosition + planeNormal2) * CFrame.new(-5, 0, 0)
return isPointInBiPlaneFrustrum(point, view.WorldPosition, planeNormal1, view.WorldPosition, planeNormal2)
and isPointInRange(point, view.WorldPosition, viewRange)
end
Here’s an illustration of what the view shape looks like, defined by a “Boss” part:
Hey its been a while since you sent this, im a bit confused on what to insert into the functions, for the cone shape without the y component, these are functions so where would i get the a,b in isPointInView, and how would I really use these in a function to check?
Whoops, looks like those were just some debugging things I forgot to remove. You should be able to just remove those two lines beginning with A.CFrame and B.CFrame.
You can use the functions to check if a specific point is inside the shape that each function represents. So if you have a list of all enemies, you can get a list of all enemies in view by looping through all enemies, checking if each one is in view, and inserting them into another table if they are.
Could you show me a way I could maybe use this idk how to use the functions well