What is the point of a coroutine if multiple functions don't actually truly fire at the same time?

In my code, I’m using the coroutine function to initiate 3 functions to run at the same time. Each of these 3 functions just sets an async to 3 different datastores. Since there isn’t a lot of time from when the player leaves and when all of their leaderstats, playergui, etc. gets deleted, I need these functions to run at the exact same time, and not one after another. So, I did some research on coroutines and here is what I came up with. Will all 3 functions run at the exact same time when the player leaves the game? No! The third function, which is the last coroutine.wrap called in the game.Players.PlayerRemoving function, is not firing in time before the client is removed from the game. If a coroutine can’t fire all 3 functions at the same time, then what is the point of using coroutines and not just placing functions one after another? Here is my code below.

function Save(player)
	local ID = currencyName.."-"..player.UserId
	DataStore:SetAsync(ID,player.leaderstats[currencyName].Value)
end
function Save2(player)
	local variable = player.PlayerGui.QuestGui.Frame.MainFrame
	LevelQuestDatastore:SetAsync(player.UserId, variable.Quest2.CoinAmount.Text)
end
function Save3(player)
	local variable = player.PlayerGui.QuestGui.Frame.MainFrame
	CoinQuestDatastore:SetAsync(player.UserId, variable.Quest1.CoinAmount.Text)
end
	

game.Players.PlayerRemoving:Connect(coroutine.wrap(Save), coroutine.wrap(Save2), coroutine.wrap(Save3))

As far as I know, coroutines are there to run code without stopping the thread it is currently residing in. They aren’t meant to run exactly at the same time, only running alongside the current thread.

ROBLOX has been testing a new feature called Parallel Lua which I’m sure runs Parallel to your thread which may be what you’re looking for: Parallel Lua Beta. Sadly, it is still in heavy beta and is not allowed outside of studio.

2 Likes

Why would you want them to run at the exact same time?

When the game.Players.PlayerRemoving function is fired, that means the player is leaving the game. What this means is that whatever data you need to save before the player is removed from the game, you have to do all that in a short period of time. This is where coroutines(or what coroutines are supposed to do) come in handy. If multiple functions run at the same time, you can save multiple pieces of data into different datastores all in different functions running at the same time right before the player leaves. Without coroutine, the functions will not run at the same time and they will run one after another, which takes up way too much time and will not save the data before the player’s character is removed from the game. My issue though is that coroutines aren’t running functions at the same time, and that’s why I am highly anticipating the release of Parallel Lua, as mentioned by @MrMoled above.

1 Like

I have never heard of this being an issue? You’re probably fine having them run one after another.

Not sure what you’re trying to do here. That’s not how :Connect works.

You should seriously consider using just one data store for player data, instead of saving to multiple keys like that.

5 Likes

Wow, what a surprise, I actually had @Tomarty reply to me! Anyways, yea I’m doing that right now. Is it fine if I send you my finished code for you to look over before I save and publish? Thanks for replying bro!

While I understand you are working to consolidate your DataStore, in the meantime, try replacing your last line with this:

game.Players.PlayerRemoving:Connect(function(player)
	coroutine.wrap(Save)(player)
	coroutine.wrap(Save2)(player)
	coroutine.wrap(Save3)(player)
end)

From my understanding, your code as written is only ever going to pass the player argument to Save and never even call Save2 or Save3.

The problem you will run into is trying to pull data from that player’s PlayerGui. This object is destroyed before that player argument even gets passed to your event connection. You will need to find a way to cache this data prior to the player leaving the game.

Ultimately, because the player’s Player object is still in-scope during your function call, it won’t get cleaned up until your done with it. Execution time shouldn’t impact things that much.