How to use coroutines properly?

Hello, I’m testing a new loading screen idea I had.

Right now I’m facing a problem that I’ve encountered a lot of times before, but just ignored because I could move my way around them in various, not so effecient ways. Today I learned about coroutines and the spawn() function. They didn’t help me because I think I’ve misunderstood the way they work (especially coroutine).

What I want is to make the “Assets loaded: 0/1535” go up as fast as the for loop does.

Like this:

And the asset name that is currently being “loaded” to be updated every second, so you can actually read it.

But of course when you wait() / yield with another function and calls it, will wait until it has run, before it continues. So this is what happens:

But what I want to happen is “Assets loaded” to go up fast, while the asset name to only update every specified time. HOW would I do that?

script.Parent.Parent:RemoveDefaultLoadingScreen()

local player = game:GetService("Players").LocalPlayer
local plrGui = player.PlayerGui

local gui = script.Parent
local background = gui:WaitForChild("Background")
local loadingText = background:WaitForChild("Loading")
local assetNameText = background:WaitForChild("Asset")

local lobby = game.Workspace:WaitForChild("Lobby")
local assetsToLoad = lobby:GetDescendants()
local total = 1535
local cp = game:GetService("ContentProvider")
local runService = game:GetService("RunService")

local tws = game:GetService("TweenService")
local tweenInfo = TweenInfo.new(3,Enum.EasingStyle.Quart,Enum.EasingDirection.Out,0,false,0)
local tween = tws:Create(background,tweenInfo,{Position = UDim2.new(0,0,-1,0)})

local remote = game.ReplicatedStorage:WaitForChild("Char")

gui.Parent = plrGui

function updateAssetName(asset)
	
	wait(1)
	assetNameText.Text = asset.Name
	
end

for index, asset in pairs(assetsToLoad) do
	
	running = true
	runService.RenderStepped:Wait()
	loadingText.Text = "Assets loaded: (" .. index .."/" .. total ..")"
	updateAssetName(asset)
	
end

loadingText.Text = "Done!"
wait(3)
tween:Play()
remote:FireServer(player)
tween.Completed:Wait(1)
gui:Destroy()
2 Likes

The best way is to remove the wait from updateAssetName function, but you can also try spawning this in a different thread using spawn(updateAssetName(asset))

The issue with spawn() is that you can’t have arguments on them. I already tried.

Maybe try using coroutine.wrap()

Also tried doing that, but could not figure out what to do as mentioned above.

You should do something like

coroutine.wrap(updateAssetName(asset))

or

coroutine.wrap(function()
    updateAssetName(asset)
end)

I guess you also misunderstand how coroutines work. :smiley:

1 Like

To be honest I never got to use coroutines before. Sometimes I just use spawn() but not that often. :smile:

1 Like

That’s completely alright, but I would prefer someone who knows exactly what to do, instead of theories.

1 Like

you can do

for i,v in pairs(assetsToLoad) do
  couroutine.wrap(function()
    updateAssetName(v)
  end)()
end

this script should work fine

Haven’t used this yet but maybe use coroutine.wrap instead

coroutine.wrap(updateAssetName)(asset)
2 Likes

In the function, updateAssetName(), yields every second due to the implementation of wait(1) - and that’s the issue identified:

wait(1) --yields every second, therefore, it slowly updates
assetNameText.Text = asset.Name

To avoid this, use a coroutine wrap as mentioned before. This will prevent yielding and go straight ahead - however, if you prefer having it update once every second whilst skipping other assets, add a debounce:

local debounce = false
function updateAssetName(asset)
    if not debounce then debounce = true else return end
    coroutine.wrap(function()
        assetNameText.Text = asset.Name
        wait(1)
        debounce = false
    end)()
end

This is a useless loading screen. ROBLOX automatically loads anything in the workspace for you, and you’re not doing any actual loading here anyways.

You should use ContentProvider:PreloadAsync() to load important assets in the game, rather than forcing the player to uselessly wait. You should also be able to use RequestQueueSize if you just wanna wait for ROBLOX to finish loading all the game’s assets to the client.

1 Like

Oh, I already know that :slight_smile: I solved the whole issue with just checking if a second has passed since the text got updated, using tick() :smiley: