Your system should be instead focused on using roblox events to prevent code from doing unneeded checks.
Calculating time should instead be used with timestamps rather than “loop ticking data”
it shouldn’t run indefinitely, a player joins → check if enough players → start round if enough → round ends → start from the beginning
I have dropped the while true statement and replaced it for the player added thing. Thank you for your help. I’m doing some bugfixing since the code now doesn’t repeat, and if someone joins, the entire thing resets.
Just wondering: Is this possible? I can’t find anything on it and it’s new knowledge to me
while true do
if #game.Players:GetPlayers() == 0 then
game.Players.PlayerAdded:Wait()
end
-- game code here
end
Uhh not sure, but probably? I mean it would be faster than starting a new server
Literally no, the game code would run indefinitely
I’m assuming this is the context of a main game loop, which is indeed, supposed to run indefinitely
I don’t know how the server backend works, but I’d think that this is possible, though less likely that a player gets put into a server with one person (unless the game allows for 2 players)
Aside from that, the case where someone joins the existing player through their profile, the “Player has left experience” thing shows
I think it’s possible but extremely rare, the backend might still linger for a second or two and the new player might have chance to be assigned to it before server closes
I do think that an event-based system for changing game states might be cleaner than a while loop–but harder to write properly
It gives off recursion vs iteration vibes
If all players leave (and we ignore the case that the server may linger with 0 players), the game ends!
As for which one is more performant, idk
Event based is obviously more performant, the while true body has to be executed every frame where the Signal function will only be executed based on the event
A while true loop is perfectly fine for this application, no point in over-engineering it
Can’t you hang a while loop so it doesn’t execute every frame?
You can, by increasing the wait time
while true do
task.wait(5)
print("this will be executed every 5s")
end
Another question, how would I prevent the game loop from starting over in the case that someone joins?
game.Players.PlayerAdded:Connect(function()
if #game:GetService("Players"):GetPlayers() <= 1 then
gameStatus.Value = "Waiting for Players"
gameTimer.Value = 0
else
while true do
-- main game loop
end
end
end)
Actually, yeah, I concur with you on how an event-based system is more performant
IT IS NOT perfectly fine, Event based is better in every point:
Cleaner for networking
Easier to sync actions like start round, end round
In general its more performant since you react to events instead of constant polling
What is your main game logic exactly? you need to react to events, one way for example where a round ends is if all players dies, check if theres currently 0 players with above 0 health and restart the round or wait again
The intermission, map revelation, the actual game, and the ending game logic is in the while true do part of the code. If you want me to send you that, here you go:
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
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)