How can I make a part that disappears when no one touches it anymore?

So, I saw in many obbies this kind of stage, but I am clueless what is the best way to implement it: say we have one brick that is solid and the next one is transparent. When player jumps on first one, the next brick becomes solid and the player can jump on it. As long as the player stays on it, I want the brick to remain unchanged. But 3 seconds after he jumps off it, I want it to become transparent back, so other players who might come would have to activate it themselves.

I tried the Touched and TouchEnded events, but the latter is very unreliable.
I read about Region3 but I’m not really comfortable with having a loop constantly running, plus I might need this for a sphere.
The third method I played with is Touched with magnitude: when player jumps on the second brick that he activated, I check the distance between him and the brick, and when it’s greater than 10, I make the brick back transparent.

						magnitude = (hit.Position - brick.Position).Magnitude
				       until magnitude > 10

But this also is problematic if during this time another player comes in on that brick and I don’t want it to become transparent anymore, but the code above calculates the distance only for the first player. I thought about keeping a list with the unique players that are on the brick at a given moment, but I am not really sure how to know when to remove a player from that list if I cannot use TouchEnded, for example.

How are stuff like these usually handled?

If you keep the stages stored in leaderstats you could just keep the parts before, ontop and infront of them and keep them active

I think I would look at it differently. I played a little before writing this post, here is a video of how it works in the end: Prototype on Disappearing Platforms

If this is what you want, here is what I did:

  1. I split the obby region in which players jump in small areas of given studs (example 4) and define each distance correctly:

    With green, you can see the Coordinate Frame of our obby course.
    We define the areaSide and xLimit to determine the size between platforms, and how thick the platforms are.

  2. Now, when you want to check where a player is, you check ONLY the Z. That’s super fast and easy to do. After you get the relative Z to the custom CF, it’s very easy to understand which regions are ‘occupied’

  3. Create some functions to setVisible and setUnvisible the areas which are occupied, based on your own logic.

Here would be the final script:

Example Script
local Players = game:GetService("Players")

local anchorCF = script.Parent.CFPart.CFrame
local areaSide = 4
local xLimit = 10

function setVisible(part)
	part.Transparency = 0
	part.CanCollide = true

function setInvisible(part)
	part.Transparency = .9
	part.CanCollide = false

local platformsGroup = script.Parent.Platforms
local platforms = platformsGroup:GetChildren()
local platformsOrdered = {}
for k, part in pairs(platforms) do
	local relativeCF = anchorCF:Inverse() * part.CFrame -- Get each platforms coordinates in our local anchorCF
	local ZIndex = ((relativeCF.p.z - relativeCF.p.z%areaSide)/areaSide)+1 -- Get each platform's index in order
	platformsOrdered[ZIndex] = part -- Store in an array the parts of the platform
	if ZIndex == 1 then setVisible(part) end

while (task.wait(.5)) do
	local activePlayers = Players:GetChildren()
	local areasOccupied = {}
	local platformsVisible = {}
	for i=1,#platformsOrdered do areasOccupied[i] = false platformsVisible[i] = false end -- initialize areas as not occupied
	for Name, plr in pairs(activePlayers) do
		local char = plr.Character
		if char == nil then continue end
		local relativeCF = anchorCF:Inverse() * char:GetPrimaryPartCFrame()
		if relativeCF.p.x < 0 or relativeCF.p.X > xLimit then continue end
		local ZIndex = ((relativeCF.p.z - relativeCF.p.z%areaSide)/areaSide)+1 -- Get each player's area index.
		if ZIndex < 1 or ZIndex > #platformsOrdered then continue end -- player is away from our area of interest.
		areasOccupied[ZIndex] = true
	--Now we know which areas have players in them. Let's look ahead and make the parts visible

	for i=1,#areasOccupied-1 do
		if areasOccupied[i] then
			platformsVisible[i] = true
			platformsVisible[i+1] = true
	for i=2,#platformsVisible do
		if platformsVisible[i] then

PS: I considered platform 1 to always be visible, since players have to understand they need to jump somewhere, ofc you can change that easily.
Also adding here the prototype I’ve built, maybe you want to check out the code:
DisappearingPlatforms.rbxl (34.3 KB)

1 Like

Uh try anything like tht

(Create number value inside script)

local a = script.Parent.Value
   a = a + 1
   a = a - 1

In another script

while true do
   if script.Parent.Value.Value == 0 then
      script.Parent.Transparency = 1
local players = game:GetService("Players")

local obbyPart1 = workspace.Part1
local obbyPart2 = workspace.Part2
local obbyPart1LastTouched = nil
	local player = players:GetPlayerFromCharacter(hit.Parent)
	if player then
		obbyPart1LastTouched = tick()
		obbyPart2.Transparency = 0
		obbyPart2.CanCollide = true

	local player = players:GetPlayerFromCharacter(hit.Parent)
	if player then
		task.delay(3, function()
			if tick() - obbyPart1LastTouched >= 3 then
				obbyPart2.Transparency = 1
				obbyPart2.CanCollide = false

Part2 appears when a player touched Part1 and then only disappears once 3 seconds have elapsed since the player last touched Part1.

wow, that was very insightful, thank you
local ZIndex = ((relativeCF.p.z - relativeCF.p.z%areaSide)/areaSide)+1
what formula is this?

I deduced it visually, to find the area Index based on a players Z coordinate.

Let’s suppose your Z position in the above picture is 10.8931
Step 1) Round the position to be a multiple of ‘areaSide’ which is 4 in the example. (0, 4, 8, 12, …):
For this, we need to obtain the orange area.
So you do:
(zPos - zPos%areaSide)
Step 2) Get the index by dividing by ‘areaside’. (Gives us 0, 1, 2, 3 ,… )
((zPos - zPos%areaSide)/areaSide)
Step 3) Since Roblox Arrays work with indexes starting from 1, not from 0, add 1.
Final formula:
((zPos - zPos%areaSide)/areaSide) + 1

1 Like