I'm not asking for anybody to do anything for me, but I just need a place to learn how to figure out this problem. I'm making a viewcone for AI - basically I attached parts to a humanoids face - and I need to make a script where when the viewcone hits any block it restrains its length all the way up to the block. This is similar to the physics of lighting, when it hits an object it does not pass through. I need this function because I want to make a stealth-based game where you can hide behind an object. Where do I start? Should I use lighting functions instead of blocks? Thank you.
Here is an amazing example: https://gyazo.com/e2c3e2d90e842c12096e50aa1fbdd93a
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.
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
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)
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