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

Any more efficient ways for Camera to occlude transparent objects?

Asked by 3 years ago

I'm making some maps for a game and the buildings are meshes that I imported from Blender, and since collisions are super wacky with meshes I'm making them non-collidable and implementing some invisible hitboxes instead. However since the hitboxes are transparent the Camera can go right through them, meaning players can have their camera go behind walls and such. I already found a fix to this which is changing the canOcclude function in one of the player scripts, but the way I did it involved having to reference each individual part, resulting in a very long string of text. Is there any more efficient way of doing this?

Here's what the function looks like at the moment for reference:

local ch = game.Workspace.Map.Cabin.Hitboxes
local cht = {
    ch.Hitbox1,
    ch.Hitbox2,
    ch.Hitbox3,
    ch.Hitbox4,
    ch.Hitbox5,
    ch.Hitbox6,
    ch.Hitbox7,
    ch.Hitbox8,
    ch.Hitbox9,
    ch.Hitbox10,
    ch.Hitbox11,
    ch.Hitbox12,
    ch.Hitbox13,
    ch.Hitbox14,
    ch.Hitbox15,
    ch.CouchHitbox1,
    ch.CouchHitbox2,
    ch.CouchHitbox3,
    ch.CouchHitbox4,
    ch.TableHitbox,
    ch.FireplaceHitbox
}

local function canOcclude(part)
    -- Occluders must be:
    -- 1. Opaque
    -- 2. Interactable
    -- 3. Not in the same assembly as the subject
    if part == cht[1] or cht[2] or cht[3] or cht[4] or cht[5] or cht[6] or cht[7] or cht[8] or cht[9] or cht[10] or cht[11] or cht[12] or cht[13] or cht[14] or cht[15] or cht[16] or cht[17] or cht[18] or cht[19] or cht[20] or cht[21] then return true end
    if FFlagUserPoppercamLooseOpacityThreshold then
        return
            part.Transparency < 0.25 and
            part.CanCollide and
            subjectRoot ~= (part:GetRootPart() or part) and
            not part:IsA('TrussPart')
    else
        return
            part.Transparency < 1 and
            part.CanCollide and
            subjectRoot ~= (part:GetRootPart() or part)
    end
end

2 answers

Log in to vote
1
Answered by 3 years ago

Try this:

local ch = game.Workspace.Map.Cabin.Hitboxes
local cht = ch:GetChildren()

local function canOcclude(part)
    -- Occluders must be:
    -- 1. Opaque
    -- 2. Interactable
    -- 3. Not in the same assembly as the subject
    for i in pairs(cht) do
        if part == cht[i] then return true end
    end
    if FFlagUserPoppercamLooseOpacityThreshold then
        return
            part.Transparency < 0.25 and
            part.CanCollide and
            subjectRoot ~= (part:GetRootPart() or part) and
            not part:IsA('TrussPart')
    else
        return
            part.Transparency < 1 and
            part.CanCollide and
            subjectRoot ~= (part:GetRootPart() or part)
    end
end

I'm not entirely sure this will work.

0
This script worked great, thanks! EnderGamer358 79 — 3y
Ad
Log in to vote
1
Answered by
SteamG00B 1633 Moderation Voter
3 years ago
Edited 3 years ago

You should always try to cut down as many if statements as you can when doing any kind of programming if you're going for efficiency. Good news for you, there is a much easier method of handling how to get the parts:

One thing to note: The canOcclude should be run in render stepped or a similar looping function for this to work in real time.

--Assuming this is a local script, then you should be able to get or already have these:
local player = game.Players.LocalPlayer
local head = player.Character.Head
local camera = workspace.CurrentCamera

--We can get the part by shooting a ray from the players head towards the player's camera, multiplied by 10 because we want to get an object behind the player's camera
function getPart()
    --second param is direction, and to get direction, we subtract the starting point from the end point
    local result = workspace:RayCast(head.CFrame.Position, (camera.CFrame.Position-head.CFrame.Position)*10)
    return result.Instance --returns the part that is behind the camera.
end

local function canOcclude()
    local part = getPart() --instead of sending the part to the function, we can get the part with our new function
    if FFlagUserPoppercamLooseOpacityThreshold then
        return
            part.Transparency < 0.25 and
            part.CanCollide and
            subjectRoot ~= (part:GetRootPart() or part) and
            not part:IsA('TrussPart')
    else
        return
            part.Transparency < 1 and
            part.CanCollide and
            subjectRoot ~= (part:GetRootPart() or part)
    end
end

0
Sorry, I should have mentioned what script it is, what I'm currently doing is editing an already existing script from the game by copying the script, editing it and pasting it into starterplayerscripts. The script in question is game.Players.LocalPlayer.PlayerModules.CameraModule.ZoomController.Popper, which from what I can tell manages camera occlusion. EnderGamer358 79 — 3y
0
Also its a modulescript EnderGamer358 79 — 3y
0
Also, I don't see why you can't use this in the copied script? You already are using the built in player scripts, so it would be quite easy to do. SteamG00B 1633 — 3y
0
No I'm just wondering if the application would be any different considering it's a module script and not a local script. EnderGamer358 79 — 3y
View all comments (2 more)
0
Why would it be different? Module scripts are just containers, it is still being called and run locally. SteamG00B 1633 — 3y
0
Idk I'm just checking just in case, I'll try it. Thanks! EnderGamer358 79 — 3y

Answer this question