When making a game, I realized that creating 90 or more ray-casts for the vision of a bad guy seems a little bit silly. So I realized that some engines use a funnel which it like a ray-cast but more spread out. I don't now how to do this in ROBLOX, so help will be appreciated.
can you make a funnel ray-cast?
2 answers
Another way to do this is to make your funnel around your target with raycasts.
Take in the number of raycasts you want, and the size of the radius for the circle being drawn around the target.
--Your start and finish positions
local start,finish = workspace.Part1,workspace.Part2
--Number of raycasts, radius size
local castRate,castRadius = 12,4
Now, since there are 360° in a circle, dividing 360 by the 'castRate' variable will get the size of each rotation increment in the circle. If you multiply this by the current iteration in a for loop, you can begin to draw the ray.
for i = 1,castRate do
--'i' is the current iteration, 360/castRate is the rotation increment
local step = i * (360/castRate);
end
Next step? Get the desired endpoint for the raycast. This is where the circle gets drawn. Multiply the 'finish' variable's CFrame by CFrame.Angles(0,math.rad(step),0) to rotate the CFrame. Here is a visual of what this does to the CFrame: before and after. Note: In real world space the '_end' CFrames would be inside the 'finish' CFrame.
for i = 1,castRate do
local step = i * (360/castRate);
--Rotate the CFrame outwards
local _end = (finish.CFrame * CFrame.Angles(0,math.rad(step),0)
end
As to why rotating the CFrame outwards is necessary.. this makes us able to "pull" the CFrame out, creating a circle. Multiply the rotated CFrame by CFrame.new(0,0,-castRadius) to move it out. Here is a visual of what that does.
So the finished product would look like this;
local start,finish = workspace.Part1,workspace.Part2
local castRate,castRadius = 12,4
for i = 1,castRate do
local step = i * (360/castRate)
local _end = (
finish.CFrame * --Origin of circle
CFrame.Angles(math.rad(step),0,0) * --Current rotation
CFrame.new(0,0,-castRadius) --Move it out
);
local ray = Ray.new( --Draw the ray
start.CFrame.p, --Start point
(_end.p - start.CFrame.p).unit * 300 --Direction of '_end' point
)
local part = workspace:FindPartOnRay(ray) --Find the part
if part ~= nil then --Check if it's real
print(part.Name) --Print the name
end
end
You can set the 'castRate' variable to any amount you want. If you think 12 raycasts is still too much then lower it to whatever number you want. But the more you lower it the less accurate the NPC's 'sight' will be.
Use trigonometry.
Take the position of anything that you want to check if it is in the bad guy's field of vision, convert it to object space of the bad guy, and take math.acos(badguy.Position.Z/badguy.Position.Magnitude), and check if the angle is within a certain amount.
badGuy = game.Workspace.BadGuy
--This function takes inputs of the object you want to check, the badGuy, and the angle range of the bad guy's field of vision
function checkObject(object,badGuy,angle)
local pos1 = badGuy.Head.Position
--Convert the point to object space
local pointToCheck = badGuy.Head:pointToObjectSpace(object.Position)
--In order to only look at the X and Z values (don't take height into account)
pointToCheck = Vector2.new(pointToCheck.X,pointToCheck.Z)
--Get the angle from the badguy
local angleGot = math.acos(pointToCheck.Y/pointToCheck.Magnitude)
--Check to see if the position is in the field of view
if angleGot < angle and angleGot > -1 * angle then
return true
else
return false
end
end
One small thing to note in my code is that the angle is the deviation from the lookVector, so if you want a 90 degree total field of vision, your angle input has to be 45 degrees.
This discussion is preserved as it was. New answers, comments, and votes are closed.

1 comment
Here is code to draw the rays in case you want a to see them physically: http://pastebin.com/kWGq6RwN