Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

can you make a funnel ray-cast?

Asked by 8 years ago

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.

2 answers

Log in to vote
2
Answered by
Goulstem 8144 Badge of Merit Moderation Voter Administrator Community Moderator
8 years ago
Edited 7 years ago

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.

0
Here is code to draw the rays in case you want a to see them physically: http://pastebin.com/kWGq6RwN Goulstem 8144 — 8y
Ad
Log in to vote
0
Answered by 8 years ago

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.

Answer this question