You don't need to think about it as "restraining" the cone against walls.
You can use raycasting combined with simple vector math to see if a point is visible in a cone. Then you can just check the Head.Position and Torso.Position to see if either is "visible" from the cone.
Step One: Cone
Let's define a Cone that has a position, a direction, and an angle (in radians).
We want to ask if a point is insideCone cone:
function insideCone(cone, point)
A cone is defined by all the lines coming from the cone's Origin that are within cone.angle of the cone.direction. Thus we can just ask if the line from cone.position to point is within cone.angle of cone.direction.
You can compute the direction from cone.point to point as just point - cone.point, and throw in a .unit to normalize (ignore distance):
local direction to = (point - cone.point).unit
There's a handy formula for dealing with angles (for unit vectors): a:Dot(b) == math.cos( angle ) Thus if we want them to be closer than angle, we want a:Dot(b) to be at least math.cos(angle):
local cosAngle = to:Dot( cone.direction.unit )
return cosAngle > math.cos( cone.angle )
end
Step Two: Visible
If it's in the cone, we also want to know whether or not the point is visible -- is any object blocking it?
If something is blocking point, then there is an object along the line from cone.position to point. We can ask what is along that ray using raycasting:
function pointVisible(cone, point)
local Ray = Ray.new(cone.position, (point - cone.position) )
local _, where = workspace:FindPartOnRay(point)
return (where - point).magnitude < 0.5
end
You can use FindPartOnRayWithIgnoreList to filter objects out that you don't mind "blocking" the view (a big thing to remember is the thing looking, itself -- you don't want its view blocked by its own hands or hat)
Step Three: Profit
These two functions together can tell you whether or not a point is visible inside a cone:
function visible(cone, point)
return pointVisible(cone, point) and insideCone(cone, point)
end
1 comment
Thank you.