If you are running into a problem when on game start textures and meshes are missing, some animations not playing and sound delaying, this tutorial will help you!
Before
After
In this tutorial i will explain right use of ContentProvider, and how to make loading menu with it.
Step 1
-
Create a new folder in ReplicatedFirst. It’s a perfect place for storing assets that must be loaded firstly.
-
Create more folders in new folder for different asset types. As example Sounds, Animations and Images
-
Put needed assets into each folder that you want load first. You dont have to put all assets used in game.
Step 2
-
Create a new ScreenGui in StarterGui, make sure to disable ResetOnSpawn and Enabled property. Enable IgnoreGuiInset property
-
Design UI in your way. In the end of tutorial there will be full game file to make sure you did everything right.
Step 3
-
Create a new LocalScript inside UI.
-
Get needed services
local contentProvider = game:GetService("ContentProvider")
local replicatedFirst = game:GetService("ReplicatedFirst")
- Create dictionary of ClassNames that can be preloaded. Used dictionary because keys faster than table.find
local preloadableClassnames = {
Decal = true,
Sound = true,
Animation = true,
ParticleEmitter = true,
Beam = true,
Trail = true,
Texture = true,
ImageLabel = true,
ImageButton = true,
MeshPart = true,
SpecialMesh = true,
SurfaceApperance = true,
Shirt = true,
Pants = true,
}
- Now we need to filter everything that should be preloaded.
local toPreload = {}
local count = 0 -- Counts how much assets have been loaded
local loaded = false -- Boolean that says if we finished loading
local workspaceContent = workspace:GetDescendants()
local replicatedFirstContent = replicatedFirst:GetDescendants()
table.move(replicatedFirstContent, 1, #replicatedFirstContent, #workspaceContent + 1, workspaceContent) -- Combines content of Workspace and ReplicatedFirst into single table
for i, v in workspaceContent do -- Loop threw combined content
if preloadableClassnames[v.ClassName] then -- Check thats content is preloadable
table.insert(toPreload, v) -- Insert content into final table
end
end
- Add a function preloadAsset. It will be called to preload one asset.
local function preloadAsset(asset: Instance)
contentProvider:PreloadAsync({asset})
count += 1
end
PreloadAsync is a ContentProvider method, that takes table of Instances as first argument and the engine attempts to load these assets from Roblox. It’s yielding, so count will be increased as soon it preloaded.
- Now make a function for starting preloading assets. First loop preloads all filtered assets in own threads. Second loop waits until game is loaded and all assets preloaded. You can add own checking into loop, as example waiting for player data from DataStore
local function Preload()
for i, v in toPreload do
task.spawn(preloadAsset, v)
end
while count < #toPreload and not game:IsLoaded() do
task.wait()
end
loaded = true
print("All assets got loaded!") -- Debug
end
task.spawn(Preload)
Step 4
- Now connect your UI to code. Define variables of your UI. They might be different if you made own UI.
local gui = script.Parent
local loadingBar = gui.LoadingBar.Inner
local percentageLabel = gui.PercentLabel
- Enable UI as soon game starts.
gui.Enabled = true
task.spawn(Preload)
- Now modify preloadAsset function
local function preloadAsset(asset: Instance)
contentProvider:PreloadAsync({asset})
count += 1
local ratio = count / #toPreload
loadingBar.Size = UDim2.fromScale(ratio, 1)
percentageLabel.Text = math.floor(ratio * 100) .. "%"
end
- Make that Preload function disables UI as soon it finished loading.
local function Preload()
for i, v in toPreload do
task.spawn(preloadAsset, v)
end
while count < #toPreload or not game:IsLoaded() do
task.wait()
end
loaded = true
gui.Enabled = false
end
And there we go, it preloading assets.
End
If you got any problem or questions, let me know. There is rbxl file of this game to make sure you did everything right.
LoadingMenu.rbxl (9.9 MB)