Custom loading screen

As a game gets larger and uses more assets it invariably takes longer to load. Instead of showing an incomplete level, it is generally preferred to show some kind of loading screen while assets are being loaded and the game is setup. Roblox provides a loading screen by default, but you can create a custom loading screen to personalize your game further.

Disabling Roblox's default loading screen[edit]

To turn off the default loading screen, insert a LocalScript into ReplicatedFirst. ReplicatedFirst is a service that replicates Instances to the client before anything else is replicated when the game is loading. Putting a LocalScript in ReplicatedFirst guarantees this script will be the first script the client runs.

In this LocalScript RemoveDefaultLoadingScreen is called to remove the default Roblox loading screen:

game.ReplicatedFirst:RemoveDefaultLoadingScreen()

Create loading screen[edit]

A loading screen can use any or all of the GUI elements that Roblox provides. These elements should be parented to the LocalPlayer's PlayerGui in a local script in ReplicatedFirst. The GUI elements can either be stored in ReplicatedFirst, or can be created by the script and put immediately into the PlayerGui. The Topbar should also be made opaque to hide any geometry that might be loading behind it.

local PlayerGui = game.Players.LocalPlayer:WaitForChild("PlayerGui")
PlayerGui:SetTopbarTransparency(0)
 
local screen = Instance.new("ScreenGui")
screen.Parent = PlayerGui
 
local textLabel = Instance.new("TextLabel")
textLabel.Text = "Loading"
textLabel.Size = UDim2.new(1,0,1,0)
textLabel.FontSize = Enum.FontSize.Size14
textLabel.Parent = screen
Note: There is a small delay when waiting for the PlayerGui. If you hide the default loading screen before you wait for the PlayerGui to load the game will be visible for a brief moment. It is recommended to wait for the PlayerGui to load first, insert the initial screen you want to display, and then hide the default loading GUI.

Hiding loading screen[edit]

At some point the loading screen should be hidden when all the loading has been finished. Even if your loading screen is intended to play for longer than the actual time needed to load (for instance showing splash screens) it is still useful to know when the game is ready to be played. Functions like RequestQueueSize and IsLoaded can be used to see if content is present in the game, but these will not say if the level has rendered or not. Therefore it is best to have your loading screens wait a set amount of time scaled on how long it takes your game to initially render.

local count = 0
local start = tick()
while tick() - start < 6 do wait() end

Example[edit]

This example code shows a loading screen while at the beginning of the game when it is placed in a LocalScript in ReplicatedFirst. It also plays a small animation while the loading screen is displayed.

local PlayerGui = game.Players.LocalPlayer:WaitForChild("PlayerGui")
PlayerGui:SetTopbarTransparency(0)
 
local screen = Instance.new("ScreenGui")
screen.Parent = PlayerGui
 
local textLabel = Instance.new("TextLabel")
textLabel.Text = "Loading"
textLabel.Size = UDim2.new(1,0,1,0)
textLabel.FontSize = Enum.FontSize.Size14
textLabel.Parent = screen
 
script.Parent:RemoveDefaultLoadingScreen()
 
local count = 0
local start = tick()
while tick() - start < 6 do
	textLabel.Text = "Loading " .. string.rep(".",count)
	count = (count + 1) % 4
	wait(.3) 
end
 
screen.Parent = nil

How to use a custom loading screen with TeleportService[edit]

If you are teleporting a player between two places you own or two places in your universe you can use the customLoadingScreen parameter of the Teleport event to create a custom loading screen when the new place is loading.

The code in the place that initiates the teleport would look like this:

-- First set up a fade out GUI to make the teleport more seamless.
local PlayerGui = game.Players.LocalPlayer:WaitForChild("PlayerGui")
PlayerGui:SetTopbarTransparency(0)
 
local screen = Instance.new("ScreenGui")
screen.Parent = PlayerGui
 
local textLabel = Instance.new("TextLabel")
textLabel.Text = "Teleporting"
textLabel.Size = UDim2.new(1,0,1,0)
textLabel.FontSize = Enum.FontSize.Size18
textLabel.BackgroundTransparency = 1
textLabel.Parent = screen
 
spawn(function()
	for i = 50, 0, -1 do
		textLabel.BackgroundTransparency = i/50
		wait()
	end
end)
 
--Initiate the teleport, passing the loading GUI you want to use as a parameter.
game:GetService("TeleportService"):Teleport(PLACE_ID, game.Players.LocalPlayer, {}, game.ReplicatedStorage.LoadingGUI)

The code in the place that receives the teleport would look like this:

game:GetService("TeleportService").LocalPlayerArrivedFromTeleport:connect(function(customLoadingScreen, data)
	spawn(function() 
		-- Spawn a function to set the top bar transparency as soon as the PlayerGui is created
		local PlayerGui = game.Players.LocalPlayer:WaitForChild("PlayerGui")
		PlayerGui:SetTopbarTransparency(0) 
	end)
	local loadingGuiScript = script.AnimateLoadingGui:Clone() -- We can add a script to animate the customLoadingScreen now, it is static while the teleport is taking place.
	loadingGuiScript.Disabled = false
	loadingGuiScript.Parent = customLoadingScreen
	wait(5) -- Wait until we want to remove the custom loading screen
	customLoadingScreen:Destroy()
end)