Detecting parts in a field of view

Hello, thanks for your time!

What I am trying to do is to detect parts in a list, in the field of another part’s view.
Problems are:

  1. The list is crowded, there are many parts and I wouldn’t like to do a big calculation for each(Small ones like magnitude calculation would be fine I guess). (Cancels out mass raycasting)
  2. Parts are not in workspace. It can be if I have to, but for now, I prefer not to put it there. (Cancels out Region3)

I tried to do a search on a devforum, but I really don’t know what to search for, so I couldn’t find a fully related post.
I wonder if it is possible to do a calculation with CFrame. I think it is, but I am not the best at math too. Would need an example.

Here’s a picture of what I need: viewpoint
Red dot in the green area should be detected, and others shouldn’t.

10 Likes

Hello! I found a topic that might help you! Check it out here!:

1 Like

Thanks for your answer!

Yes, it is possible to do raycasting, but I would love to avoid mass raycasting to prevent lag. It’s a crowded list to check.
Also, that code doesn’t check if part really can see other part w/ it’s view angle or not. I am adding a picture to main question to demonstrate what I really need :slightly_smiling_face:

1 Like

Hello guys, i’m just gonna say that this isn’t a good practice to use, thanks for reading.
I tried to make a scary game time ago, in first person only, i attached something like you made here:
3f9077340f3e260857f35db12b829f80652f25da
And guess when the player is looking, and where, sizing it to the field of view.

And identify with a touch event what items are touching there. Remember set the “Physical field of view” massless!

If you want to make it in 3rd person, then make a part which is attached to the camera which will be the camera position, and attack the part to this Physical FoV! I hope this helps :+1:

1 Like

You can do this without raycasting, but it won’t be able to check for obstructions.

The way to do this is by simply measuring the angle between both objects. This can be done by taking the arc-cosine from the dot product of two normal vectors (i.e. look vectors). In your use-case, you would use the part’s direction, then find the direction to the point you’re checking by simply subtracting the two positions and using that unit vector (i.e. normal vector).

A function to check the angle might look like this:

local function AngleBetween(vectorA, vectorB)
	return math.acos(math.clamp(vectorA:Dot(vectorB), -1, 1))
end

It’s important to note again that the above function expects unit vectors. A unit vector is simply a vector whose magnitude is 1. The .Unit property of a vector will return this.


Ok, so to see if your point is within a certain field of view from a part, you first need to grab the correct vectors to check. In this code, I will use part to represent the gray block where the FOV is coming from, and will use point to represent the part that is being checked.

Let’s get our vectors:

-- Imagine this as a line coming straight through the center of your FOV sweep:
local lookForward = part.CFrame.LookVector

-- Imagine this as a line going directly to the point we're checking:
local lookToPoint = (point.Position - part.Position).Unit

Now that we have our two look vectors, we can measure the angle between them. We simply feed them into our AngleBetween function:

local angle = AngleBetween(lookForward, lookToPoint)

Now we have our angle (in radians). We can now check if it’s within our FOV range. But we need to be careful! The angle will be a measurement from the center. Therefore, we need to measure the absolute angle (simply use math.abs) and then check based on half of our defined FOV range.

So if our FOV range is defined as 70°, then we need to check if the absolute angle measured is within half of 70°, so we would simply check if it’s less or equal to 35°.

local FOV = math.rad(70)

-- All the other code we wrote goes here

if math.abs(angle) <= FOV / 2 then
   print("Within range!")
else
   print("Not within range")
end

Ok, so altogether now!

-- Field of view (in degrees):
local FOV = 70

-- Define stuff:
local part = workspace.Part
local point = workspace.Point
local fovCheck = math.rad(FOV) / 2

-- Find angle between two normalized vectors:
local function AngleBetween(vectorA, vectorB)
	return math.acos(math.clamp(vectorA:Dot(vectorB), -1, 1))
end

-- Get the two lookvectors:
local lookForward = part.CFrame.LookVector
local lookToPoint = (point.Position - part.Position).Unit

-- Calculate angle between our two lookvectors:
local angle = AngleBetween(lookForward, lookToPoint)

-- Check if the angle is within range:
if math.abs(angle) <= fovCheck then
   print("Within range!")
else
   print("Not within range")
end

Final note: This is basing the origin and direction of the FOV from the lookvector of that gray part. In your image, most likely you’re casting from the right or left. If you want to continue doing that, you can change the definition of lookForward to use the RightVector. You can simply negate it for the left vector.

36 Likes

Thank you for your answer!
I can’t use touched event, because as I said before, parts are not in Workspace. Thanks for the effort though!

1 Like

Thank you for your answer!
I perfectly understood what to do thanks to your telling and examples! (And also happy that a legend answered my question :smile: )
Have a lovely day!

2 Likes