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.
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.
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:
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.
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’
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
end
function setInvisible(part)
part.Transparency = .9
part.CanCollide = false
end
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
setInvisible(part)
if ZIndex == 1 then setVisible(part) end
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
end
--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
end
end
for i=2,#platformsVisible do
if platformsVisible[i] then
setVisible(platformsOrdered[i])
else
setInvisible(platformsOrdered[i])
end
end
end
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)
local players = game:GetService("Players")
local obbyPart1 = workspace.Part1
local obbyPart2 = workspace.Part2
local obbyPart1LastTouched = nil
obbyPart1.Touched:Connect(function(hit)
local player = players:GetPlayerFromCharacter(hit.Parent)
if player then
obbyPart1LastTouched = tick()
obbyPart2.Transparency = 0
obbyPart2.CanCollide = true
end
end)
obbyPart1.TouchEnded:Connect(function(hit)
local player = players:GetPlayerFromCharacter(hit.Parent)
if player then
task.delay(3, function()
if tick() - obbyPart1LastTouched >= 3 then
obbyPart2.Transparency = 1
obbyPart2.CanCollide = false
end
end)
end
end)
Part2 appears when a player touched Part1 and then only disappears once 3 seconds have elapsed since the player last touched Part1.
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