Working with RayIgnoreList?

I’m currently working on a Camera system that’s functioned using Rays -
The Ray is generated from the Players Y axis, as it finds the name of the Part above the Player and if it’s present, then the changes apply.
However, this has proven problematic as other Parts in the Players Y axis intrude on this and cause it to revert to the normal Camera.

I was wondering if there were a way to add all parts bar the required part to the IgnoreList and if so how would I go about it?

If anyone has any other ideas, I would be very appreciative.

local RunService = game:GetService("RunService")
local Player = game.Players.LocalPlayer
repeat wait(1) until Player.Character ~= nil
local Character = Player.Character

local RunService = game:GetService("RunService")

local Player = game.Players.LocalPlayer

repeat wait(1) until Player.Character ~= nil

local Character = Player.Character

RunService.RenderStepped:Connect(function()

local ray = Ray.new(Character:WaitForChild("Head").CFrame.p, Character:WaitForChild("Head").CFrame.p + Vector3.new(0, 50, 0))

local part, hitPosition = workspace:FindPartOnRay(ray, Character)

if part.Name == "CamTrigger" then game.Workspace.Camera.CFrame = CFrame.new(workspace["NewCam"].CFrame.p)
else
end
end)

https://i.gyazo.com/f47ccafac2760544707d70a0f80be740.mp4

1 Like

Why not use :FindPartOnRayWithWhiteList?

2 Likes

Is there a way I could use that, despite other blocks being in the Y Axis also?

Yes. Using FindPartOnRayWithWhiteList ignores all blocks not inside the WhiteList array.

1 Like

Thank you,
How would I go about making it so that it only finds parts named “CamTrigger”? I’ve tried this method but keep getting the error: Unable to cast Value to Object.

local WhiteList = {"CamTrigger"}

local ray = Ray.new(Character:WaitForChild("Head").CFrame.p, Character:WaitForChild("Head").CFrame.p + Vector3.new(0, 50, 0))

local part, hitPosition = workspace:FindPartOnRayWithWhitelist(ray, WhiteList)

if part.Name == WhiteList then game.Workspace.Camera.CFrame = CFrame.new(workspace["NewCam"].CFrame.p)

else

end

Transpiled:

local RunService = game:GetService("RunService")
local Player = game.Players.LocalPlayer
repeat wait(1) until Player.Character ~= nil
local Character = Player.Character

local RunService = game:GetService("RunService")

local Player = game.Players.LocalPlayer

repeat wait(1) until Player.Character ~= nil

local Character = Player.Character

RunService.RenderStepped:Connect(function()

    local ray = Ray.new(
        Character:WaitForChild("Head").CFrame.p, 
        Character:WaitForChild("Head").CFrame.p + Vector3.new(0, 50, 0)
    )

    local part, hitPosition = workspace:FindPartOnRay(ray, Character)

    if part.Name == "CamTrigger" then
        game.Workspace.Camera.CFrame = CFrame.new(workspace["NewCam"].CFrame.p)
    else

    end
end)

Well, if you want a really inefficient method, you can do this.

local function createWhiteList()
    local whiteListTb = {}
    for _, part in next, workspace:GetDescendants() do
        if part:IsA"BasePart" and part.Name == "CamTrigger" then
            table.insert(whiteListTb, part)
        end
    end
    return whiteListTb
end

Now, the real question is: Will the whitelist contents be changing over time?
If the answer to this question is yes, then you would need to do something like this:

game:GetService"RunService":BindToRenderStep("CamCheck", Enum.RenderPriority.Camera.Value + 1, function()
    local ray = Ray.new(Character:WaitForChild("Head").CFrame.p, Character:WaitForChild("Head").CFrame.p + Vector3.new(0, 50, 0))
    local part, hitPosition = workspace:FindPartOnRayWithWhiteList(ray, createWhiteList())
    if part then
         -- do stuff
    end
end)

However, if the whitelist contents won’t be changing at all, then you can simply initialize the WhiteList array outside of a loop/event and use that same table throughout to save some space.

Note: I said the above method is inefficient because there’s a better way of doing this

Put all the CamTrigger parts inside a folder in workspace named “CamTriggerFolder”, and use that as the WhiteList.

Something like this

local part, hitPosition = workspace:FindPartOnRayWithWhiteList(ray, workspace.CamTriggerFolder:GetChildren())

How’s that look?

4 Likes

Actually works perfectly!
If I were to implement this into a chunk loading system, per say the Player enters a house that is loaded with said CamTrigger on it, would a simple .Changed function work well with this? Or upon the loading of the Chunk, would it be simple to create a new Part and parent it to the folder, and upon removal of said Chunk the trigger is also removed?

I’m not sure what you mean by using a .Changed function.

Sorry, I should of elaborated or perhaps used the wrong function -
But, per-say a model is inserted via the Chunk loader, it registers the change [Now realised it would be ChildAdded] and then gets the trigger from within the block and so forth?

If the part is added to the collection of CamTriggers, you would need to constantly update the WhiteList array. (If that’s what you’re asking)

1 Like

Yes, along those lines I believe?

The trigger would be inside different chunks of the map which are loaded differently when Players pass into them, travel to them, etc.

So, the Chunks will be locally placed in the Players workspace, along with the trigger and was wondering if those newly inserted triggers are accessible the same way?

Yes, as long as you constantly update the WhiteList.

You can also make it so the chunks’ Triggers are parented to the CamTriggerFolder in workspace, nested inside other folders that indicate which chunk it’s a part of (so you can remove it along with the chunk when necessary).

1 Like

This is how I had done it, and it’s turned out perfectly! This way means that it constantly finds the triggers, even if new ones are inserted.

https://i.gyazo.com/fcbfffad97c9661f0b53788f2ccb357d.mp4

RunService.RenderStepped:Connect(function()

local whiteListTb = {}

for _,v in pairs (workspace:GetDescendants()) do

if v.Name == "CamTrigger" then

table.insert(whiteListTb, v)

local ray = Ray.new(Character:WaitForChild("Head").CFrame.p, Character:WaitForChild("HumanoidRootPart").CFrame.p + Vector3.new(0, 50, 0))

local part, hitPosition = workspace:FindPartOnRayWithWhitelist(ray, whiteListTb)

if part then

workspace.Camera.CFrame = CFrame.new(part.Parent["CamPos"].CFrame.p, part.Parent["CamFocus"].CFrame.p)

else end

else end

end

end)
2 Likes