3 Player System not working

I’m trying to make a system where the game doesn’t start unless there’s 3 or more players.
It doesn’t seem to execute the scripting when the players get to 3.
I’ve tried a for loop to count the players, I’ve tried using a variable to get the amount, Example:

local OnlinePlayers = game.Players:GetPlayers()
if #OnlinePlayers >= 3 then
      -- blah blah blah
end
local Players = game:GetService("Players")
local OnlinePlayers = Players:GetPlayers()

if #OnlinePlayers >= 3 then
	for Number, Player in pairs(OnlinePlayers) do
		if Player.TeamColor == BrickColor.new("Institutional white") then
			Player.Character:FindFirstChild("HumanoidRootPart").Position = Vector3.new(0, 1, 0)
			Player.TeamColor = BrickColor.new("Dark stone grey")
		end
	end
end
5 Likes

Have you placed this part on a loop, or a Players.PlayerAdded connection?

if #OnlinePlayers >= 3 then
	for Number, Player in pairs(OnlinePlayers) do
		if Player.TeamColor == BrickColor.new("Institutional white") then
			Player.Character:FindFirstChild("HumanoidRootPart").Position = Vector3.new(0, 1, 0)
			Player.TeamColor = BrickColor.new("Dark stone grey")
		end
	end
end

If not then it’ll only check it once, so you’ll need to either put it in a loop or a Players.PlayerAdded connection

4 Likes

Dont loop it, instead make it count online players when a player gets added.

3 Likes

ServerScript in ServerScriptService

I would say that you listen when a player joins the game and then hear an Int by 1. Once you have 3 players in the game you can loop through all players as you have done

local Players = game:GetService("Players")

local CurrentPlayer = 0

Players.PlayerAdded:Connect(function(Plr)
	
	CurrentPlayer += 1
	
	if CurrentPlayer >= 3 then
		
		for _, Player in pairs(Players:GetChildren()) do
			
			if Player.TeamColor == BrickColor.new("Institutional white") then
				
				Player.Character:FindFirstChild("HumanoidRootPart").Position = Vector3.new(0, 1, 0)
				Player.TeamColor = BrickColor.new("Dark stone grey")
				
			end
			
		end
		
	end
	
end)

It is important that you also reduce the player when he leaves the game.

Players.PlayerRemoving:Connect(function(Plr)
	
	CurrentPlayer -= 1
	
end)
3 Likes

This will only run once, when the server starts, and when the server starts there likely won’t be any players whatsoever, you have to keep track of the players that join and leave

local Players = game:GetService('Players')
local playerCount = 0

local playerAddedConnection
playerAddedConnection = Players.PlayerAdded:Connect(function()
	playerCount += 1 -- Add 1 to the player count when a player joins
	if playerCount == 3 then
		playerAddedConnection:Disconnect()
		-- Start the game
	end
end)

Players.PlayerRemoving:Connect(function()
	playerCount -= 1 -- Remove 1 from the player count when a player exits
end)
4 Likes

No need to do a player count, you can keep checking how many players there are in the server each time you’re attempting to start the game.

local PlayerService = game:GetService("Players")

local function StartGame()
    if #PlayerService:GetPlayers() >= 3 then
        --Attribute teams ect...
    end
end

PlayerService.PlayerAdded:Connect(StartGame)

Here’s another way to do it, in case the game can start only once and new players can join while the game has already started.

local PlayerService = game:GetService("Players")
local GameStarted = false

local function StartGame()
    GameStarted = true
    --Spawn and attribute team to all players
end

local function JoinGame(NewPlayer)
    --Spawn and attribute team to NewPlayer
end

PlayerService.PlayerAdded:Connect(function(NewPlayer)
    if #PlayerService:GetPlayers() >= 3 and GameStarted == false then
        StartGame()
    elseif GameStarted == true then
        JoinGame(NewPlayer)
    end
end)
4 Likes

This is a great way of doing it :+1:

1 Like

You realize that the player count is intentional, right? It’s much faster and better to simply add and check a number than having to call :GetPlayers() and getting the length of a table when a player joins the server

1 Like

Yes

Not really, you got a useless active variable and an additional connection (player removing) only for it while #PlayerService:GetPlayers() is the only thing you could do to get the exact same result… it take less memory usage and save up 5 lines of code, but you’re still free to do it however you want if you prefer your method over mine.

1 Like

I’m pretty sure yours is right, although it didn’t work:

local PlayerService = game:GetService("Players")

local function StartGame()
	if #PlayerService:GetPlayers() >= 3 then
		for _, Player in pairs(PlayerService:GetPlayers()) do
			if Player.TeamColor == BrickColor.new("Institutional white") then
				Player.TeamColor = BrickColor.new("Dark stone grey")
			end
			Player.Character.HumanoidRootPart.Position = Vector3.new(0, 1, 0)
		end
	end
end

PlayerService.PlayerAdded:Connect(StartGame)

Sorry for responding late!

1 Like

The code you have should work, despite some changes needing to be made. Have you confirmed whether or not the script is running?

1 Like

There are some mistakes, you need to change the HumanoidRootPart.CFrame instead of the position as the character is a group of objects, and you need to wait for the character to be spawned before trying to move it.

You also need to make sure that the default starter team is BrickColor.new("Institutional white"), because the real default one could be either White or Medium stone grey.

It’s a matter of personal preferences, but you can also remove pairs when using for in do, because in is the luau generalized version and it does the exact same thing than pairs, so i find it better to remove it as it reduce code lenght a bit.


Example1

local PlayerService = game:GetService("Players")

local function StartGame()
	if #PlayerService:GetPlayers() >= 1 then --1 to test
		for _, Player in PlayerService:GetPlayers() do
			local Character = Player.Character or Player.CharacterAdded:Wait()
			local Root = Character and Character:WaitForChild("HumanoidRootPart")
			
			if Player.TeamColor == BrickColor.new("Institutional white") then
				Player.TeamColor = BrickColor.new("Dark stone grey")
			end
			
			if Root then
				Root.CFrame = CFrame.new(Vector3.new(0, 1, 0))
			end
		end
	end
end

PlayerService.PlayerAdded:Connect(StartGame)

Example2

local PlayerService = game:GetService("Players")

local function MoveCharacterWhenRespawn(Character)
	local Root = Character and Character:WaitForChild("HumanoidRootPart")
	
	if Root then
		Root.CFrame = CFrame.new(Vector3.new(0, 1, 0))
	end
end

local function StartGame()
	for _, Player in PlayerService:GetPlayers() do
		if Player.TeamColor == BrickColor.new("Institutional white") then
			Player.TeamColor = BrickColor.new("Dark stone grey")
		end
	end
end

PlayerService.PlayerAdded:Connect(function(NewPlayer)
	if #PlayerService:GetPlayers() >= 1 then --1 to test
		StartGame()
	end
	
	NewPlayer.CharacterAdded:Connect(function(NewCharacter)
		MoveCharacterWhenRespawn(NewCharacter)
	end)
end)
1 Like

I don’t really get how the memory usage of a number changes much (as it is only around 4 bytes), but having to call :GetPlayers(), count the items in the table and compare the count, seems like it would be slower than to compare a numeric value once, the speed it takes to start the game however may not be that important

Guys I solved it, it was a really simple fix.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.