I wrote a neat demo for this a couple years ago https://devforum.roblox.com/t/area-zoning/19151
Here’s some math that does it without FindPartOnRay
local function PointInPolygon(Point, Polygon)
local current = Polygon
local inside = false
local A = current.Position
local ax, az = A.X, A.Z
local px, pz = Point.X, Point.Z
repeat
local B = current.Next.Position
local bx, bz = B.X, B.Z
if ((az >= pz) ~= (bz >= pz)) and ((px - ax) <= (bx - ax)*(pz - az)/(bz - az)) then
inside = not inside
end
current = current.Next
A, ax, az = B, bx, bz
until current == Polygon
return inside
end
local function CreatePolygonFromPoints(Points)
local Polygon = {Position = Points[1]}
local First = Polygon
for i = 2, #Points do
Polygon.Next = {Previous = Polygon, Position = Points[i]}
Polygon = Polygon.Next
end
Polygon.Next, First.Previous = First, Polygon
return First
end
CreatePolygonFromPoints takes a table of Vector3s and returns a “Polygon”, which is a circular doubly linked list of vertices. PointInPolygon takes a point and a polygon and returns whether the point is inside that polygon.