Seamless Transition When Teleporting from Place to Place

I’m hoping someone can help me create a smooth fade transition from one place to another when teleporting. I’ve outline the steps for this effect here:

Essentially if a player is transitioning from one place to another, the following will happen from their perspective:

  1. Player screen shows Place A
  2. Player screen fades out to black
  3. Player screen will remain black while player teleports from Place A to Place B
  4. Player screen fades in to world
  5. Player screen shows Place B

This doc was somewhat helpful: Teleporting Between Places | Roblox Creator Documentation but there are a lot of moving parts to this in the server, client and ReplicatedFirst to have the fade effect be smooth. I’m also confused where / when I should create the FadeGui or destroy it, or maybe pass it from place to place using TeleportService:SetTeleportGui(teleportGui)(?)

Thanks in advance for the help!

2 Likes
local Game = game
local TweenService = Game:GetService("TweenService")
local ReplicatedFirst = Game:GetService("ReplicatedFirst")
ReplicatedFirst:RemoveDefaultLoadingScreen()
local Players = Game:GetService("Players")
local LocalPlayer = Players.LocalPlayer

local LoadingScreenGui = Instance.new("ScreenGui")
LoadingScreenGui.Name = "LoadingScreenGui"
LoadingScreenGui.IgnoreGuiInset = true
LoadingScreenGui.ResetOnSpawn = false

local LoadingScreenFrame = Instance.new("Frame")
LoadingScreenFrame.Name = "LoadingScreenFrame"
LoadingScreenFrame.BackgroundColor3 = Color3.new(0, 0, 0)
LoadingScreenFrame.Size = UDim2.new(1, 0, 1, 0)
LoadingScreenFrame.Parent = LoadingScreenGui

local PlayerGui = LocalPlayer:WaitForChild("PlayerGui")
LoadingScreenGui.Parent = PlayerGui

local Tween = TweenService:Create(LoadingScreenFrame, TweenInfo.new(5), {BackgroundTransparency = 1}) --Change '5'.
Tween:Play()

local function OnTeleport(TeleportState)
	if TeleportState.Name == "InProgress" then
		if Tween then Tween:Cancel() end
		Tween = TweenService:Create(LoadingScreenFrame, TweenInfo.new(3), {BackgroundTransparency = 0}) --Change '3'.
	end
end

LocalPlayer.OnTeleport:Connect(OnTeleport)
1 Like

Hey Forummer, thanks for the code snippet and response. However, it doesn’t quite achieve what I had in mind. I did the following to test this:

  1. Created a game with 2 places
  2. Put your code snippet as a local script within ReplicatedFirst for both places
  3. Added a simple server script to each place to teleport the player to the other place after 15 seconds

And here is the result:

Two issues:

  1. The fade out to black doesn’t seem to be happening quick enough, the player gets teleported before their screen fades to black
  2. The player still sees the default loading screen when entering the new place

Any ideas on fixing those two issues?

  1. The fade out to black doesn’t seem to be happening quick enough, the player gets teleported before their screen fades to black
if TeleportState.Name == "InProgress" then

Changing ‘InProgress’ to ‘Started’ may resolve this, alternatively you could play the tween, wait for its completion via TweenBase:Completed:Wait() and then issue the teleport request.

  1. The player still sees the default loading screen when entering the new place

Could be a bug relating to RemoveDefaultLoadingScreen.

I don’t think there is a bug… I think you need to set the gui to load immediately with TeleportService:SetTeleportGui(teleportGui). The fade is less important then having a consistent screen for the entire duration of the teleport to make the transition seamless.

Doors does this well with a black “Loading…” screen for example:

There’s a small hiccup when changing servers but it’s pretty much the best you can do at the moment I think. I’ll continue to play around with this… appreciate the help though.

TeleportService:SetTeleportGui(teleportGui)

This sets the gui when teleporting from a place not the gui when teleporting to a place. If RemoveDefaultLoadingScreen isn’t working for you then its either a bug (related to the API method) or an issue with your game’s setup.

All I have in the test game is the code you posted within ReplicatedFirst and a simple server script to teleport the player. Are you seeing the same thing I’m seeing when testing?

The purpose of showing the Doors example is to show that there is not a bug with RemoveDefaultLoadingScreen as they seem to be correctly using it.

You can use

 TeleportService:GetArrivingTeleportGui()

Doc on this: TeleportService:GetArrivingTeleportGui

https://developer.roblox.com/en-us/api-reference/event/TeleportService/LocalPlayerArrivedFromTeleport
Would likely be more useful in this case (it passes the arriving teleport gui as the first argument to any connected callback function(s)).

local Game = game
local ReplicatedFirst = Game:GetService("ReplicatedFirst")
ReplicatedFirst:RemoveDefaultLoadingScreen()
local TeleportService = Game:GetService("TeleportService")
local TweenService = Game:GetService("TweenService")
local Players = Game:GetService("Players")
local LocalPlayer = Players.LocalPlayer
local PlayerGui = LocalPlayer:WaitForChild("PlayerGui")

local function OnPlayerTeleport(TeleportStatus)
	if TeleportStatus.Name ~= "Started" then return end
	local FadeIn = TweenService:Create(PlayerGui.LoadingScreenGui.LoadingScreenFrame, TweenInfo.new(5), {BackgroundTransparency = 0}) --Fade in tween.
end

local function OnLocalPlayerArrivedFromTeleport(LoadingScreenGui)
	TeleportService:SetTeleportGui(LoadingScreenGui)
	local FadeOut = TweenService:Create(LoadingScreenGui.LoadingScreenFrame, TweenInfo.new(5), {BackgroundTransparency = 1}) --Fade out tween.
	FadeOut:Play()
end

LocalPlayer.OnTeleport:Connect(OnPlayerTeleport)
TeleportService.LocalPlayerArrivedFromTeleport:Connect(OnLocalPlayerArrivedFromTeleport)

local LoadingScreenGui = TeleportService:GetArrivingTeleportGui()
if not LoadingScreenGui then
	LoadingScreenGui = Instance.new("ScreenGui")
	LoadingScreenGui.Name = "LoadingScreenGui"
	LoadingScreenGui.IgnoreGuiInset = true
	LoadingScreenGui.ResetOnSpawn = false
	LoadingScreenGui.Parent = PlayerGui
	
	local LoadingScreenFrame = Instance.new("Frame")
	LoadingScreenFrame.Name = "LoadingScreenFrame"
	LoadingScreenFrame.BackgroundColor3 = Color3.new(0, 0, 0)
	LoadingScreenFrame.Size = UDim2.new(1, 0, 1, 0)
	LoadingScreenFrame.Parent = LoadingScreenGui
	
	task.spawn(OnLocalPlayerArrivedFromTeleport, LoadingScreenGui)
end

I realized the real problem I’m trying to solve is keeping a black screen on throughout teleporting, then I can always fade the black screen out and in before and after teleporting respectively.

It’s actually recommended to use TeleportService:GetLocalPlayerTeleportData() and TeleportService:GetArrivingTeleportGui() instead of LocalPlayerArrivedFromTeleport (see TeleportService | Roblox Creator Documentation)

I found something that works:
In ReplicatedFirst LocalScript

local ReplicatedFirst = game:GetService("ReplicatedFirst")
-- Remove default loading screen
ReplicatedFirst:RemoveDefaultLoadingScreen()

local TeleportService = game:GetService("TeleportService")
-- Get arriving teleport gui
local loadingGui = TeleportService:GetArrivingTeleportGui()

local guiToAddToPlayer
if not loadingGui then
	-- player entered experience
	guiToAddToPlayer = ReplicatedFirst.EnterGui
else
	-- player entered place from other place within experience
	guiToAddToPlayer = loadingGui
end

local Players = game:GetService("Players")
local playerGui = Players.LocalPlayer:WaitForChild("PlayerGui")
-- Set local player's gui to guiToAddToPlayer
guiToAddToPlayer.Parent = playerGui

-- Wait some time (can do gui animations here)
task.wait(5)

-- Destroy the gui
guiToAddToPlayer:Destroy()

I created two guis - one for entering the experience (EnterGui), and one for teleporting from another place within the experience (LoadingGui). guiToAddToPlayer is only needed for the start place, any other place would always use loadingGui.

Only other thing you need is to set the teleport gui on the Client:
In StarterPlayerScripts LocalScript

local TeleportService = game:GetService("TeleportService")
local ReplicatedFirst = game:GetService("ReplicatedFirst")

TeleportService:SetTeleportGui(ReplicatedFirst:WaitForChild("LoadingGui"))

Here’s what the result looks like:

The API is all over the place for TeleportService… appreciate the help.

1 Like

When fetching teleportData and the customLoadingScreen you are advised to use TeleportService:GetLocalPlayerTeleportData() and TeleportService:GetArrivingTeleportGui() instead. This is because these functions can be called immediately without having to wait for this event to fire.

The event fired immediately for me when testing and I considered it the better approach as it provides both the loading screen gui and teleport data in a single operation rather than two individual operations (more performant). The snippet I provided does use GetArrivingTeleportGui too.

Additionally the documentation proceeds to provide a code snippet similar to mine indicating that the event/signal should be used for loading screens/teleport data.

local TeleportService = game:GetService("TeleportService")
local Players = game:GetService("Players")
local ReplicatedFirst = game:GetService("ReplicatedFirst")

TeleportService.LocalPlayerArrivedFromTeleport:Connect(function(customLoadingScreen, teleportData)
    local playerGui = Players.LocalPlayer:WaitForChild("PlayerGui")
    ReplicatedFirst:RemoveDefaultLoadingScreen()

    customLoadingScreen.Parent = playerGui
    -- animate screen here
    wait(5)
    -- destroy screen
    customLoadingScreen:Destroy()
end)
1 Like