Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

Any more efficient ways for Camera to occlude transparent objects?

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

✓ Accepted answer

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.

1 comment

0

This script worked great, thanks!

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

6 comments

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.

0

Also its a modulescript

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.

0

No I'm just wondering if the application would be any different considering it's a module script and not a local script.

0

Why would it be different? Module scripts are just containers, it is still being called and run locally.

0

Idk I'm just checking just in case, I'll try it. Thanks!

This discussion is preserved as it was. New answers, comments, and votes are closed.