Updating Table Values During While Loop

My code is similar to this:

local playingPeople = {
    player1,
    player2,
}

local plotOwners = {
    [1] = player1,
    [2] = player2,
}

local function startGameLoop()
    while #playingPeople > 1 do
        -- do some stuff
        -- do more stuff with plotOwners table
    end
end

startGameLoop()

When a player leaves the game, I get an error saying x is not a valid member, or infinite yield x:WaitForChild().

How could I make it so when a player leaves, I can update the table values of ‘playingPeople’ and ‘plotOwners’ to remove the player.

Anything is appreciated, I’ve tried looking for similar posts but this seems a little niche. Thanks.

1 Like

Check before doin some stuff that player exist in the game and havent leaved it.


local function startGameLoop()
    while #playingPeople > 1 do
        if player
        -- do some stuff
        -- do more stuff with plotOwners table
      end
    end
end

Is there a more efficient way of doing this as it is a round based system with like 20 functions accessing the same tables.

Use PlayerAdded and PlayerRemoving to your advantage.

Will these fire asynchronous to my while loop?

No these will fire whenever a player is added or removed in your game. So its suggested you put them outside any loops. More information on the links.

image

What I meant was will playerRemoving fire while my loop is running, I just tried it and the playerRemoving event doesn’t fire.

playerRemoving fires when a player has left the game. Using the given player variable you could remove the player from your tables.

I understand what you are saying, but PlayerRemoving does not process as the while loop is running.

while true do

end

game.Players.PlayerRemoving:Connect(function()
    -- CODE INSIDE HERE WILL NOT RUN BECAUSE WHILE LOOP IS ONGOING
end)

but why would you need that instead a while loop when you have an already connected event that fires whenever the player is removed? You don’t need a while true loop since it would keep on connecting new playerRemoving functions. Putting it outside connects it once. If you want to update a table you can simply use the table methods to achieve the following:

game.Players.PlayerRemoving:Connect(function(plr)
	-- Finds table key using player name
	local key = table.find(plotOwners, plr.Name)
	-- Removes player from table
	table.remove(plotOwners, key)
end)

Note: this can be done for any other table. I just don’t want you to just paste whatever I write and be brainded to what I’m actually trying to say.

1 Like

This does not run because a while loop is ongoing. If the while loop was over sure it would work.

you would write this on top of the while loop (Edit: or do what was below said depending on the context → More info on Coroutines here).

Run the loop in a coroutine if you need it to run separately.

1 Like

I was considering this and gave it a shot, my script waits for the function startGameLoop() to end in order to start a new game. Would this be achievable using a coroutine whilst also picking up playerRemoving events at the same time?

If you aren’t as experienced and just want a simple fix I suggest just using the

Coroutine.wrap(function()
end)()

around the while loop
If it becomes complex I suggest you plan out a framework with different module scripts.

1 Like

Sure - just use the game loop to only do things for each player and use those Player events to handle modification of the game table when a player joins or leaves

1 Like

Define the Connection before the loop:

game.Players.PlayerRemoving:Connect(function()
    -- This will run on a different thread (asynchronously)
end)

while true do

end
1 Like

This solved my issue, just a quick question to add on.

My while loop runs within another while loop, should I put the playerRemoving outside of both while loops? I can’t imagine creating a new thread for the same function would be great for performance. I’ll show below what I mean.

game.Players.PlayerRemoving:Connect(function()
    -- This will run on a different thread (asynchronously)
end)

while true do
    while players > 1 do
        -- stuff
    end
end

I’ve made a module script framework using OOP, would this be better than @DiscoDino01 's solution?

Just asking as I’d like to optimise performance considering the amount of data I will be handling at the same time is pretty large.

Thanks for everyone’s efforts :smiley:

You should use event-driven approach (if possible) instead of using polling approach (using while true loops).

local playerQueue = {}:: {Player}
function add(plr)
    table.insert(playerQueue, plr)
end

function remove(plr)
    local i = table.find(playerQueue, plr)
    return i and table.remove(playerQueue, i)
end

-- Event-driven/Interrupt approach
Players.PlayerAdded:Connect(add)
Players.PlayerRemoving:Connect(remove)

-- Polling approach
while true do
    local playerList = Players:GetPlayers():: {Player}
    for i, player in playerList do
        if not table.find(playerQueue, player) then add(player) end
    end

    for i, player in playerQueue do
        if not table.find(playerList, player) then remove(player) end
    end
end

Asking if you can’t use event-driven and why.

1 Like