So, i am making a game where players go through a bunch of rooms, and every time a door is opened, there is a new randomly generated room behind it. Since i am deleting the previous rooms for optimization, and to avoid generated rooms from clashing with each other, i delete the third room everytime a new room is created.
So in order to prevent players from proceeding further without other players being present, i’ve created this system that counts every player that has entered the room, and removes them when they leave. I’ve done this by using 2 seperate triggers on the each side of the entrance door.
When the players open a door, it is declared as the entrance door, and every other door in both rooms are locked. Once all the players have entered the room, the entrance door gets locked, and the other doors are unlocked. I have achieved this using the names of the instances instead of tags / variables / physical values. It took me a while to get it right, and works perfectly fine too. I am quite happy with it, but i would still like to get a second opinion on how else i could’ve done it. I feel like this method is a less convenient one.
local debounce = {}
local playersentered = 0
script.Parent.Entered.Touched:Connect(function(player)
if player.Parent:FindFirstChild("Humanoid") then
if not debounce[player.Parent.Name] then
debounce[player.Parent.Name] = true
local plrlist = game.Players:GetChildren() --getting plrlist within the touch function cause it was a simple solution for now, i will be implementing a loading screen to wait on all players in the future. But i feel like it is also a great solution to make sure the player list is constantly updated to account for leavers.
local plrcount = #plrlist -- i could probably just use #plrlist in the if statement instead of setting this variable but, oh well.
local char = player.Parent
playersentered = playersentered + 1
if playersentered == plrcount then
for _, descendant in pairs(script.Parent.Parent:GetDescendants()) do
if descendant:IsA("Model") and descendant.Name == "EntranceDoor" then
descendant.Name = "LockedEntranceDoor"
elseif descendant:IsA("Model") and descendant.Name == "LockedDoor" then
task.delay(2, function() --delay to wait for the door closing animation to finish
if script.Parent.Parent:FindFirstChild("LockedEntranceDoor") and descendant.Name == "LockedDoor" then
descendant.Name = "Door"
end
end)
end
end
elseif playersentered < plrcount then
for _, descendant in pairs(script.Parent.Parent:GetDescendants()) do
if descendant:IsA("Model") and descendant.Name == "Door" then
descendant.Name = "LockedDoor"
end
end
end
end
end
end)
script.Parent.Exited.Touched:Connect(function(player)
if player.Parent:FindFirstChild("Humanoid") then
if debounce[player.Parent.Name] == true then
debounce[player.Parent.Name] = nil
local plrlist = game.Players:GetChildren()
local plrcount = #plrlist
local char = player.Parent
playersentered = playersentered - 1
if playersentered < plrcount then
for _, descendant in pairs(script.Parent.Parent:GetDescendants()) do
if descendant:IsA("Model") and descendant.Name == "LockedEntranceDoor" then
descendant.Name = "EntranceDoor"
elseif descendant:IsA("Model") and descendant.Name == "Door" then
descendant.Name = "LockedDoor"
end
end
end
end
end
end)
I have thought of using one large trigger zone inside of rooms to detect all players, and using TouchEnded
to remove them, but player limbs poking through walls and doors has proven it to be too finicky and unreliable, especially compared to the 2 trigger method. Though i feel like i could add a check for HumanoidRootPart specifically to avoid this.
Plus like i have mentioned before, I am using instance names instead of variables and stuff, which works perfectly fine, but im not sure how reliable it would be compared to actual variables