If, Else doesn't work

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”

2 Likes

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

1 Like

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

1 Like

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
1 Like

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

1 Like

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)