My game loop resets when a player joins. I know the problem, although I don’t know how to fix it.
I asked other people, although the solution was disputed, so I chose to move it here.
local gameStatus = game.ReplicatedStorage:WaitForChild("GameStatus")
local gameTimer = game.ReplicatedStorage:WaitForChild("TimerStatus")
local lobbyCFrame = workspace:WaitForChild("Lobby"):WaitForChild("SpawnLocation").CFrame + Vector3.yAxis*5
local maps = game.ReplicatedStorage.Maps:GetChildren()
local mapsLength = #maps
local random = math.random(1, mapsLength)
local chosenMap = maps[random]
local mapName = chosenMap.Name
local INTERMISSION = 0
local ROUNDLENGTH = 300
game.Players.PlayerAdded:Connect(function()
if #game:GetService("Players"):GetPlayers() <= 1 then
gameStatus.Value = "Waiting for Players"
gameTimer.Value = 0
game.Players.PlayerAdded:Wait()
else
while true do
for countDown = INTERMISSION, 0, -1 do
gameStatus.Value = "Intermission"
gameTimer.Value = countDown
task.wait(1)
end
for countDown = 5, 0, -1 do
gameStatus.Value = "Map Name: "..mapName
gameTimer.Value = countDown
task.wait(1)
end
local map = chosenMap:Clone()
map.Parent = workspace
local players = game.Players:GetChildren()
for i = 1, #players do
if players[i].Character ~= nil then
local spawnLocation = math.random(1, #map.Teleports:GetChildren())
players[i].Character:MoveTo(map.Teleports:GetChildren()[spawnLocation].Position)
players[i].Character.Parent = workspace.InGame
end
end
local children = workspace.InGame:GetChildren()
for i = 1, #children do
local swordClone = map.ClassicSword:Clone()
local rocketLauncherClone = map.RocketLauncher:Clone()
local timebombClone = map.ClassicTimebomb:Clone()
swordClone.Parent = children[i]
rocketLauncherClone.Parent = children[i]
timebombClone.Parent = children[i]
end
map.ClassicSword:Destroy()
map.RocketLauncher:Destroy()
map.ClassicTimebomb:Destroy()
repeat
ROUNDLENGTH = ROUNDLENGTH - 1
gameStatus.Value = "Game in Progress"
gameTimer.Value = ROUNDLENGTH
task.wait(1)
until ROUNDLENGTH == 0 or #workspace.InGame:GetChildren() == 0 or #workspace.InGame:GetChildren() == 1
if #workspace.InGame:GetChildren() == 1 then
gameStatus.Value = workspace.InGame:FindFirstChildWhichIsA("Model").Name.. " has won."
task.wait(5)
map:Destroy()
for i = 1, #players do
if players[i].Character ~= nil then
players[i].Character.Parent = workspace
end
end
end
for _, player in ipairs(game.Players:GetPlayers()) do
player.Character:BreakJoints()
end
ROUNDLENGTH = 300
end
end
end)
well… you’ve built the entire loop system into the function for when a player joins. Its a no-brainer that it’d reset because its coded to do that.
You need to have the loop work externally, because this system is just poorly written in many ways.
local INTERMISSION = 15
... --// Other variables
while task.wait(INTERMISSION) do --// We use intermission here as to not overflow the loop.
if #game.Players:GetPlayers() <= 1 then
gameStatus.Value = "Waiting for Players"
gameTimer.Value = 0
continue --// Restart the loop instead of starting a new round.
end
--// rewrite round logic here, do NOT use playerAdded in this.
--// More importantly, don't create any connections here without disconnecting them.
end
I’ve provided code that would fix the problem, it strips away the PlayerAdded connection and gives you general advice in comments.
I’m not going to rewrite your entire system as I have my own things to work on. The rest of the code you have in your loop might work, it just needs to be ported into the new loop I’ve provided, however may require some rewrites here and there.
This should fix your problem, it’ll wait for at least one player before running the game loop.
local Players = game:GetService("Players")
local gameStatus = game.ReplicatedStorage:WaitForChild("GameStatus")
local gameTimer = game.ReplicatedStorage:WaitForChild("TimerStatus")
local lobbyCFrame = workspace:WaitForChild("Lobby"):WaitForChild("SpawnLocation").CFrame + Vector3.yAxis*5
local maps = game.ReplicatedStorage.Maps:GetChildren()
local mapsLength = #maps
local random = math.random(1, mapsLength)
local chosenMap = maps[random]
local mapName = chosenMap.Name
local INTERMISSION = 0
local ROUNDLENGTH = 300
local function getPlayerCount() : number
return #Players:GetPlayers()
end
while true do
if getPlayerCount() == 0 then
gameStatus.Value = "Waiting for Players"
gameTimer.Value = 0
Players.PlayerAdded:Wait()
end
for countDown = INTERMISSION, 0, -1 do
gameStatus.Value = "Intermission"
gameTimer.Value = countDown
task.wait(1)
end
for countDown = 5, 0, -1 do
gameStatus.Value = "Map Name: "..mapName
gameTimer.Value = countDown
task.wait(1)
end
local map = chosenMap:Clone()
map.Parent = workspace
local players = game.Players:GetChildren()
for i = 1, #players do
if players[i].Character ~= nil then
local spawnLocation = math.random(1, #map.Teleports:GetChildren())
players[i].Character:MoveTo(map.Teleports:GetChildren()[spawnLocation].Position)
players[i].Character.Parent = workspace.InGame
end
end
local children = workspace.InGame:GetChildren()
for i = 1, #children do
local swordClone = map.ClassicSword:Clone()
local rocketLauncherClone = map.RocketLauncher:Clone()
local timebombClone = map.ClassicTimebomb:Clone()
swordClone.Parent = children[i]
rocketLauncherClone.Parent = children[i]
timebombClone.Parent = children[i]
end
map.ClassicSword:Destroy()
map.RocketLauncher:Destroy()
map.ClassicTimebomb:Destroy()
repeat
ROUNDLENGTH = ROUNDLENGTH - 1
gameStatus.Value = "Game in Progress"
gameTimer.Value = ROUNDLENGTH
task.wait(1)
until ROUNDLENGTH == 0 or #workspace.InGame:GetChildren() == 0 or #workspace.InGame:GetChildren() == 1
if #workspace.InGame:GetChildren() == 1 then
gameStatus.Value = workspace.InGame:FindFirstChildWhichIsA("Model").Name.. " has won."
task.wait(5)
map:Destroy()
for i = 1, #players do
if players[i].Character ~= nil then
players[i].Character.Parent = workspace
end
end
end
for _, player in ipairs(game.Players:GetPlayers()) do
player.Character:BreakJoints()
end
ROUNDLENGTH = 300
end
The reason your game loop resets when a player joins is because all of your round code is running inside the PlayerAdded event. Every time a new player joins the PlayerAdded function fires (duh) and since your loop is inside it it effectively restarts the round logic for everyone!
A better approach is to separate your game loop from the PlayerAdded event. You can still use PlayerAdded to handle individual player setup (like moving them to the lobby) but the main game loop should run independently for example in a while true do loop in a server script that checks the number of players and progresses through intermissions, rounds and map spawning.
-- player setup
game.Players.PlayerAdded:Connect(function(player)
-- move player to lobby set up character, and whatevr
end)
-- game loop
task.spawn(function()
while true do
if #game.Players:GetPlayers() >= 2 then
-- intermission, map selection, spawn players, round logic, etc.
else
gameStatus.Value = "Waiting for Players"
gameTimer.Value = 0
task.wait(1)
end
end
end)
This way new players can join without resetting the round!
By separating player handling and game loop code you avoid resetting the round when someone joins.
You might also consider tracking the round state with a variable so joining players can be placed correctly depending on whether a round is in progress!
local gameRunning = false
game.Players.PlayerAdded:Connect(function()
--your unrelated player code
if gameRunning then return end
gameRunning = true
--your game start code
--on round end call:
gameRunning = false
end)
Additionally, as other mentioned, I think that it is better if you rely on a while loop for this. To wait for players you can call game.Players.PlayerAdded:Wait() which yields the code until the event fires, and when it does it runs the lines below it(so when a player is added).
No don’t do this, simply take out your game login from the player added event, this is not where your game logic should be. Put it in a server script where it runs once the game starts, then run a function or add something when a player joins.
I provided a template, not a full script. Please for the love of god, don’t expect people here to fully rewrite everything all the time.
What I provided will work given you can re-implement round logic. I read your problem, I gave you a template to fix your problem. I’d argue its better practice for you to re-implement logic (even if just a copy-paste) as its more effort than relying on people the same way someone would rely on ChatGPT to program.
The first comment was well written including an example he spent time writing. That is the backbone of the average round system with 5 descriptive comments providing the skeleton of how to make it. You didn’t have to respond like that someone being nice. Nobody is paid to take time to help you.
My brother in christ does a backbone for a system not explain to you how to approach the problem?
Remove PlayerAdded.
Move the loop elsewhere and make it repeatedly loop until the required amount of players is met
That’s literally what I wrote out for you. That is how you should go about approaching it.
Please for the love of god get off the forums if you’re going to be this incompetent and ignore the solutions to your problems because they weren’t spoonfed to you the same way ChatGPT would.
does a backbone for a system not explain to you how to approach the problem?
no, its quite literally the opposite of what i wanted, you told me “do NOT use playerAdded in this”, despite the fact that I knew the problem was there.
Please for the love of god get off the forums
no
if you’re going to be this incomptent
> someone asks a question > you answer the wrong thing > they tell you it’s the wrong thing > you get angry
My solution tells you what you apparently already knew and how to fix it. You’ve had 2 other replies saying damn near the exact same thing I did. I have given you the solution, you have received the solution 3 TIMES.
We have told you “how to go about fixing it” 3 TIMES. We have supplied code 3 TIMES.
And you’re just ignoring it.
My code fixes the problem. I take the loop outside of the player added connection and rewrite the round start logic to be contained within the loop. The other 2 solutions do the exact same thing in slightly different methods.
dude. Its as simple as you don’t use player added.
Move the loop outside and make the player count check happen within the loop. You literally just don’t use player added. The code I wrote is literally what you should do to fix the problem.