Optimising loading script for my game

  1. What do you want to achieve? Keep it simple and clear!
    So exactly, my loading script and process tooks forever to load. It is around 48k parts in full game.
    image
    And this loading is already like 5-10 mins
  2. What is the issue? Include screenshots / videos if possible!
    Loading takes too much
  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub? That’s code i wrote by myself, though now i see it kinda not optimised.

Code:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ReplicatedFirst = game:GetService("ReplicatedFirst")
local ContentProvider = game:GetService("ContentProvider")
local TweenService = game:GetService("TweenService")
local LoadGame = workspace:WaitForChild("Events").LoadGame
local Assets = game:GetDescendants()
local UI1 = script.LoadingGUI:Clone()
local camera = workspace.CurrentCamera
local Player = game:GetService("Players").LocalPlayer
local pName = Player.Name
local PlayerGui = Player:WaitForChild("PlayerGui")
ReplicatedFirst:RemoveDefaultLoadingScreen()

local instance = Instance.new("BoolValue")
instance.Name = "isLoading"
instance.Parent = Player
instance.Value = true


UI1.Parent = PlayerGui

for i=1, #Assets do
	local asset = Assets[i]	
	ContentProvider:PreloadAsync({asset})
	UI1.MainFrame.Loading.ProgressBar.AssetLabel.Text = "Loading Assets..."..asset.Name.." ("..i.."/"..#Assets..")"
	UI1.MainFrame.Loading.ProgressBar.Filler:TweenSize(UDim2.new(1/(#Assets/i), 0, 1, 0), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.1, false)
	if #Assets/i == 1 then
		UI1.MainFrame.Loading.ProgressBar.Filler:TweenSize(UDim2.new(1, 0, 1, 0), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.1, false)	
	end	
end
local Character = workspace:FindFirstChild(pName)
Character:WaitForChild("Humanoid").WalkSpeed = 0
Character:WaitForChild("Humanoid").JumpPower = 0
	instance.Value = false
	UI1.MainFrame:TweenPosition(UDim2.new(-1.5, 0, 0, 0), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 2, false, function()
	UI1.MainFrame.Visible = false
	for _,drops in pairs(UI1.MainFrame.Loading.DropsFolder:GetChildren()) do
		drops:Destroy()
	end
	UI1.Menu.LoadingLabel:TweenPosition(UDim2.new(0.25, 0, 0.3, 0), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.5, false, function()
	UI1.Menu.PlayButton:TweenPosition(UDim2.new(0.25, 0, 0.4, 0), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.5, false, function()
	UI1.Menu.DonateMenuButton:TweenPosition(UDim2.new(0.25, 0, 0.525, 0), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.5, false, function()
	UI1.Menu.SettingsButton:TweenPosition(UDim2.new(0.25, 0, 0.65, 0), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.5, false, function()	
	end)				
	end)
	end)	
	end)	
	end)
	UI1.Menu.PlayButton.TextButton.MouseEnter:Connect(function()
		UI1.Menu.PlayButton.Hover.Visible = true
		UI1.Menu.PlayButton.Hover:TweenSize(UDim2.new(1,0,0.5,1), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.5, true)
	end)
	UI1.Menu.DonateMenuButton.TextButton.MouseEnter:Connect(function()
		UI1.Menu.DonateMenuButton.Hover.Visible = true
		UI1.Menu.DonateMenuButton.Hover:TweenSize(UDim2.new(1,0,0.5,1), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.5, true)
	end)
	UI1.Menu.SettingsButton.TextButton.MouseEnter:Connect(function()
		UI1.Menu.SettingsButton.Hover.Visible = true	
		UI1.Menu.SettingsButton.Hover:TweenSize(UDim2.new(1,0,0.5,1), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.5, true)
	end)
    UI1.Menu.PlayButton.TextButton.MouseLeave:Connect(function()
	UI1.Menu.PlayButton.Hover:TweenSize(UDim2.new(1,0,0,1), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.5, true, function()
		UI1.Menu.PlayButton.Hover.Visible = false
	end)
	end)
	UI1.Menu.DonateMenuButton.TextButton.MouseLeave:Connect(function()
	UI1.Menu.DonateMenuButton.Hover:TweenSize(UDim2.new(1,0,0,1), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.5, true, function()
		UI1.Menu.DonateMenuButton.Hover.Visible = false
	end)
	end)
	UI1.Menu.SettingsButton.TextButton.MouseLeave:Connect(function()
	UI1.Menu.SettingsButton.Hover:TweenSize(UDim2.new(1,0,0,1), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.5, true, function()
		UI1.Menu.SettingsButton.Hover.Visible = false
	end)
	end)
	UI1.Menu.PlayButton.TextButton.MouseButton1Click:Connect(function()
	UI1.Menu.LoadingLabel:TweenPosition(UDim2.new(0.25, 0, -1.3, 0), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.5, false, function()
	UI1.Menu.PlayButton:TweenPosition(UDim2.new(0.25, 0, -1.4, 0), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.5, false, function()
	UI1.Menu.DonateMenuButton:TweenPosition(UDim2.new(0.25, 0, -1.525, 0), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.5, false, function()
	UI1.Menu.SettingsButton:TweenPosition(UDim2.new(0.25, 0, -1.65, 0), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.5, false, function()		
	LoadGame:FireServer()
	end)				
	end)
	end)	
	end)
	end)
print("Done")

Note: I don’t ask for full script rewriting, just some tips about optimization, like spending 30 mins for SMALL game load it is very much

The thing is that you don’t need to and shouldn’t be preloading everything in your game, you should just be preloading assets that need to be prioritized. If you’re loading everything at once, that completely voids :PreloadAsync of any use.

1 Like

Take a look at a former post of mine that solves this issue:

Sorry for late ask, but what then i should preload?

local assets = game:getDescendants()

Use something different or what?

Bumping topic (30 lettersssssssssss)

It is highly unrecommended to load the entire game at once. The loading screen should only be for loading things that are immediately avaliable (i.e. the HUD)

You might have heard this a thousand times now.

Yeah right, i’m asking about what should i now load as preloadables. Like variable which i should load. You mean i just need to preload everything except workspace?

It depends. But most of the time, you would be preloading your StarterGui, Tools and a part of your workspace thats closer to spawn.

referring back,

It depends.

Sometimes games have enemies that fight you immediately upon loading, or a cutscene begins playing/intro sequence.

Those are things you need to preload. as it would suck to fight an invisible enemy or watch a cutscene where half the characters and the map is invisible.

Oh alright thank you, though i’m using that loading for tycoon and some incremental games lol, so i need just preload starterGUI, and some animations things.

Hey just asking, how could i get everything except workspace. Like:

local Assets = game:GetDescendants() 
--and somehow exclude workspace frm here

you really shouldn’t use game:GetDescendants() as it includes many things that is hidden from the explorer and shouldnt need any of your attention. (>30000 objects iirc)

just use a table and loop through your Services and appending the contents of :GetDescendants() from those said services into the assets table.

I done something like that lol.

local Assets = {
	game.Players:GetDescendants(),
	game.Lighting:GetDescendants(),
	game.MaterialService:GetDescendants(),
	game.ReplicatedStorage:GetDescendants(),
	game.ReplicatedFirst:GetDescendants(),
	game.StarterGui:GetDescendants(),
	game.StarterPack:GetDescendants(),
	game.StarterPlayer:GetDescendants(),
}

Is that what you meant?

Sorta, you should use unpack() to not make them into tables within tables.

It is not necessary to load the entire workspace. This basically selects everything in your game. ContentProvider is only nesessary for the assets contained within. Content provider handles this.

So:
ContentProvider:PreloadAsync({game})
is the same as
ContentProvider:PreloadAsync({game:GetDescendants()})
but much slower.

Here is a snippet from one of my loading screens.

If you need to have a counter make a count of the assets before you push your game to production.

local Assets = 0
	ContentProvider:PreloadAsync({game,game:GetService("CoreGui")},function(asset: string,assetFetch:Enum.AssetFetchStatus)
		LoadingText.Text = assetFetch.Name.." loading "..asset
		Assets += 1
		--task.wait()
	end)
	LoadingText.Text = "Loading..."
	print(Assets," assets loaded.")

Also ContentProvider:Preload includes a callback function which is definitely very useful which means no more for loops.


OH and one more thing you don’t need to include the CoreGui in as it is already on the clients device.(I just put it in because some of my games barely have any assets)

Ugh, can you kinda make small script please, def my break from roblox scripting on .5 year made me forget everything lol.
image
Well i mixed up somethin xd

local Assets = {
	unpack(game.Players:GetDescendants()),
	unpack(game.Lighting:GetDescendants()),
	unpack(game.MaterialService:GetDescendants()),
	unpack(game.ReplicatedStorage:GetDescendants()),
	unpack(game.ReplicatedFirst:GetDescendants()),
	unpack(game.StarterGui:GetDescendants()),
	unpack(game.StarterPack:GetDescendants()),
	unpack(game.StarterPlayer:GetDescendants()),
}

Well 62 assets smhw now, is that even normal? Also loading is infinite now :/.
image
This second asset is loading around 1 min

That means your game only has 62 assets that is absolutely nessecary to load, i’d suppose.

Well, it is kinda awkard i think. Only 62 assets, idk

I haven’t seen one instance where I’ve joined a game and lighting was the one that was the slowest to load. It appears that this is where the issue occurs so I would say to remove lighting from the assets to load.