Region3 Player Counter Error

So I’m using Region3 to detect how many players there’s in a zone, but I got a problem, when there are no players in the Zone I want to change the SurfaceGuiText of a block to “0 / 12” Players, If the player leaves the zone it does change ONLY If there are more than 2 players, but If there is only one and he exits the zone the “SurfaceGuiText” Doesn’t change from “1 / 12” to “0 / 12”

I know there is a lot of good people in the DevForum, so If you can give me a hand with this I’ll be very very grateful to you! :smile: :wink:

Here’s the script:



image

Instead of if Players[0] then use if #Players == 0 then the # symbol in Lua is known as the length operator and when followed by a literal table/variable reference to a table its result is the total number of items/entries which belong to that table. You can use it for the other conditional checks too.

If you wanted to make the code more efficient you could also simply do the following:

if Players then
	game.Workspace.GuiRealShowerCounter.SurfaceGui.PlayerLeftText.Text = #Players.." / 12"
end

This, but you might also consider doing:

game.Workspace.GuiRealShowerCounter.SurfaceGui.PlayerLeftText.Text = tostring(#Players) .. " / 12"

instead of your massive if…then chain

I did offer that as a possible solution but ultimately left it up to the original poster if they wanted to implement it or not, since it’s their conditional chain they may want to keep it in the future for some other purpose.

Also you don’t need to tostring() the length of players since when you concatenate anything with a string in Lua it is automatically converted into a string.

There’s a much simpler approach in my opinion. Lets start with the array of players.

playersinzone = {};

Now, we can populate the list with characters that are in the region by doing the following:

for i, part in pairs(partsinregion3) do
    local player = game.Players:GetPlayerFromCharacter(part.Parent)
    -- Check for a valid player and add them to the list if they're not in it.
    if (player and playersinzone[player] == nil) then
        -- The value can be set to anything. This is keeping a reference to the character.
        playersinzone[player] = player.Character;
    end
end

-- Update the label.
game.Workspace.GuiRealShowerCounter.SurfaceGui.PlayerLeftText.Text = #playersinzone.." / 12"

Note: This is converting the array to a dictionary. You can still access the player’s normally by indexing with playersinzone[0] for example.

1 Like

As you can see in his code if Players[2] is true some additional actions are performed. Let’s not sidetrack the thread anymore, a viable solution has been provided.

image

Checking your edits, you did not offer that as a possible solution until I had informed OP of it, but no matter. Was just adding some additional clarification to your post that OP might find useful.

Appreciate it, I can never remember specifically which languages require direct conversion, and without the use of an IDE/linter/compiler, I couldn’t verify this so I errored on the side of caution.

That’s a great point actually, it looks like OP made an additional mistake here by including Players[3] in a table of length 2.

As for fixing the if…then chain, if you just need to do something when the array is of size 2, you can throw a check into that such that:

if Players then
	game.Workspace.GuiRealShowerCounter.SurfaceGui.PlayerLeftText.Text = #Players.." / 12"

    if #Players == 2 then
        -- do something
    end
end

Thank you for trying to help me but It doesn’t fix the bug for the moment, I’m gonna try other ways but thank you equally !

image

This is because even if 12 players are present your first conditional statement will be satisfied. Players[1] will be satisfied first even when 12 players are in the server. You can fix this by reversing the order of the conditional checks.

1 Like

Was just a copy & paste of a comment I gave someone else who had a similar issue, I’ll edit it accordingly.

Deleted my comment because it’s no longer relevant. When you say reversing the order of conditional checks do you mean while sticking with the if Players[n] then end convention?

Thanks but it still doesn’t work :wink:
image
image

Try @Exeplex solution. It should grab the players and updates the label according to your request.

local playersinzone = {}

for i, part in pairs(partsinregion3) do
    local player = game.Players:GetPlayerFromCharacter(part.Parent)
    -- Check for a valid player and add them to the list if they're not in it.
    if (player and playersinzone[player] == nil) then
        -- The value can be set to anything. This is keeping a reference to the character.
        playersinzone[player] = player.Character;
    end
end

-- Update the label.
game.Workspace.GuiRealShowerCounter.SurfaceGui.PlayerLeftText.Text = #playersinzone.." / 12"

In your code, you can remove the for loop starting from:

for i, Part in pairs(partsInRegion) do

You can also remove the for loop nesting the text label change statements.

Could you copy & paste the script here please?

Thank you but It breaks completely the script :+1:

Just copy & paste the script here please so we can make the necessary edits.

local playerFound = false
local TeleportService = game:GetService(‘TeleportService’)

function CreateRegion3FromPart(Part)
return Region3.new(Part.Position-(Part.Size/2), Part.Position+(Part.Size/2))
end

function GetPlayersInPart(part)
local region = CreateRegion3FromPart(part)
local partsInRegion = game.Workspace:FindPartsInRegion3(region,nil,math.huge)
local Players = {}

for i, Part in pairs(partsInRegion) do
	local player = game.Players:GetPlayerFromCharacter(Part.Parent)
	if player then
		
		for i, v in pairs(Players) do
			if Players[i].Name == player.Name  then
				playerFound = true
			end
		end
		
		if playerFound == false then
			table.insert(Players, player)
		end
		playerFound = false
	end
end

for i, v in pairs(Players) do
	if #Players == 12  then
		print('Changed the text')
		game.Workspace.GuiRealShowerCounter.SurfaceGui.PlayerLeftText.Text = '12 / 12'
	end
	if #Players == 11 then
		print('Changed the text')
		game.Workspace.GuiRealShowerCounter.SurfaceGui.PlayerLeftText.Text = '11 / 12'
	end
	if #Players == 10 then
		game.Workspace.GuiRealShowerCounter.SurfaceGui.PlayerLeftText.Text = '10 / 12'
	end
	if #Players == 9 then
		game.Workspace.GuiRealShowerCounter.SurfaceGui.PlayerLeftText.Text = '9 / 12'
	end
	if #Players == 8 then
		game.Workspace.GuiRealShowerCounter.SurfaceGui.PlayerLeftText.Text = '8 / 12'
	end
	if #Players == 7 then
		game.Workspace.GuiRealShowerCounter.SurfaceGui.PlayerLeftText.Text = '7 / 12'
	end
	if #Players == 6 then
		game.Workspace.GuiRealShowerCounter.SurfaceGui.PlayerLeftText.Text = '6 / 12'
	end
	if #Players == 5 then
		game.Workspace.GuiRealShowerCounter.SurfaceGui.PlayerLeftText.Text = '5 / 12'
	end
	if #Players == 4 then
		game.Workspace.GuiRealShowerCounter.SurfaceGui.PlayerLeftText.Text = '4 / 12'
	end
	if #Players == 3 then
		game.Workspace.GuiRealShowerCounter.SurfaceGui.PlayerLeftText.Text = '3 / 12'
	end
	if #Players == 2 then
		game.Workspace.GuiRealShowerCounter.SurfaceGui.PlayerLeftText.Text = '2 / 12'
		TeleportService:Teleport(7832693088, Players[1])
		TeleportService:Teleport(7832693088, Players[2])
		TeleportService:Teleport(7832693088, Players[3])
	end
	if #Players == 1 then
		game.Workspace.GuiRealShowerCounter.SurfaceGui.PlayerLeftText.Text = '1 / 12'
	end
	if #Players == 0 then
		game.Workspace.GuiRealShowerCounter.SurfaceGui.PlayerLeftText.Text = '0 / 12'
	end
end
return Players

end

while wait(0.1) do
GetPlayersInPart(game.Workspace.Detector)
end

local playerFound = false
local TeleportService = game:GetService("TeleportService")

function CreateRegion3FromPart(Part)
	return Region3.new(Part.Position-(Part.Size/2), Part.Position+(Part.Size/2))
end

function GetPlayersInPart(part)
	local region = CreateRegion3FromPart(part)
	local partsInRegion = game.Workspace:FindPartsInRegion3(region, nil, math.huge)
	local Players = {}

	for i, Part in pairs(partsInRegion) do
		local player = game.Players:GetPlayerFromCharacter(Part.Parent)
		if player then

			for i, v in pairs(Players) do
				if Players[i].Name == player.Name  then
					playerFound = true
				end
			end

			if playerFound == false then
				table.insert(Players, player)
			end
			playerFound = false
		end
	end
	game.Workspace.GuiRealShowerCounter.SurfaceGui.PlayerLeftText.Text = #Players.." / 12"
	for i, v in pairs(Players) do
		if #Players == 2 then
			TeleportService:Teleport(7832693088, Players[1])
			TeleportService:Teleport(7832693088, Players[2])
		end
	end
	return Players
end

while task.wait() do
	GetPlayersInPart(game.Workspace.Detector)
end

Providing the script you provided worked, this should work.

1 Like
function GetPlayersInPart(part)
    local region = CreateRegion3FromPart(part)
    local partsInRegion = game.Workspace:FindPartsInRegion3(region,nil,math.huge)
    local playersinzone = {}

    for i, part in pairs(partsinregion3) do
        local player = game.Players:GetPlayerFromCharacter(part.Parent)
        -- Check for a valid player and add them to the list if they're not in it.
        if (player and playersinzone[player] == nil) then
            -- The value can be set to anything. This is keeping a reference to the character.
            playersinzone[player] = player.Character;
        end
    end

    -- Update the label.
    game.Workspace.GuiRealShowerCounter.SurfaceGui.PlayerLeftText.Text = #playersinzone.." / 12"

    if (#playersinzone == 3) then
        for player, char in pairs(playersinzone) do
            TeleportService:Teleport(7832693088, player)
        end
    end
end
local playerFound = false
local TeleportService = game:GetService("TeleportService")

function CreateRegion3FromPart(Part)
	return Region3.new(Part.Position-(Part.Size/2), Part.Position+(Part.Size/2))
end

function GetPlayersInPart(part)
	local region = CreateRegion3FromPart(part)
	local partsInRegion = game.Workspace:FindPartsInRegion3(region, nil, math.huge)
	local Players = {}

	for i, Part in pairs(partsInRegion) do
		local player = game.Players:GetPlayerFromCharacter(Part.Parent)
		if player then

			for i, v in pairs(Players) do
				if Players[i].Name == player.Name  then
					playerFound = true
				end
			end

			if playerFound == false then
				table.insert(Players, player)
			end
			playerFound = false
		end
	end
	game.Workspace.GuiRealShowerCounter.SurfaceGui.PlayerLeftText.Text = #Players.." / 12"
	for i, v in pairs(Players) do
		TeleportService:Teleport(7832693088, Players[i])
	end
	return Players
end

while task.wait() do
	GetPlayersInPart(game.Workspace.Detector)
end

This slight change will teleport all players (regardless of how many players there are).

1 Like