I’m making a theme park game, and each ride is separated into different places within the same experience.
When a player exits that place, they have to touch a part that will teleport them.
But when they arrive at the Start Place, it puts them on the default SpawnPoint.
When I say Start Place, I mean the MAIN place within the entire experience, the one that all players join when they press the green play button on the Roblox page for the game.
What can I use so that it teleports them to a specific point in that Start Place, like a cframe position when they arrive from the other place? Instead of the main default SpawnPoint.
I am not much of a scripter, but I have attempted using TeleportData.
local TeleportService = game:GetService("TeleportService")
local targetPlaceId = 123456789 -- The ID of your Start Place
function teleportPlayer(player)
local teleportData = {
arrivalPoint = "SpecificSpawnPoint" -- Identifier for your specific spawn point
}
TeleportService:TeleportAsync(targetPlaceId, {player}, teleportData)
end
Step 2: Reading TeleportData Upon Arrival
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(character)
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
-- Assuming you have a RemoteEvent for receiving teleport data
local teleportDataEvent = ReplicatedStorage:WaitForChild("TeleportDataEvent")
teleportDataEvent.OnClientEvent:Connect(function(data)
if data and data.arrivalPoint == "SpecificSpawnPoint" then
-- Set to the CFrame of the specific point you want
humanoidRootPart.CFrame = CFrame.new(x, y, z) -- Replace x, y, z with your coordinates
end
end)
end)
end)
Step 3: Sending TeleportData to the LocalScript
local TeleportService = game:GetService("TeleportService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Ensure you have a RemoteEvent named TeleportDataEvent in ReplicatedStorage
local teleportDataEvent = ReplicatedStorage:WaitForChild("TeleportDataEvent")
Players.PlayerAdded:Connect(function(player)
player.OnTeleport:Connect(function(state, placeId, teleportData)
if state == Enum.TeleportState.InProgress and teleportData then
-- Wait until the player's character is loaded to ensure the client script is ready
player.CharacterAdded:Wait()
-- Fire the RemoteEvent to the client with the teleport data
teleportDataEvent:FireClient(player, teleportData)
end
end)
end)
You need remote events and replace the Cframe position there
According to the Roblox Creator Documentation, the third argument for TeleportService:TeleportAsync() does not accept a standard table.
It only accepts a TeleportOptions object that has been assigned a value with TeleportService:SetTeleportData(). With that function, you can then assign a table to it, and then pass the TeleportOptions through as the third argument for the :TeleportAsync() call.
The rest of the code you posted is generally ok, except for some specific sections, including:
In “Step 2”, where it’s unnecessarily connecting OnClientEvent to a new function every single time the player’s Character respawns. Furthermore, given that the server already receives the TeleportOptions in the example code from “Step 3”, there shouldn’t be a need to communicate that to the client since the server could teleport the player’s Character directly to the intended spawnpoint / CFrame right then and there.
In “Step 3”, player.OnTeleport is being used to detect when a player arrives from a teleport, but if I understand correctly, after reading the documentation, that event is meant to be used before teleporting a player to a new place:
OnTeleport
Fired when the TeleportState of a player changes. This event is useful for detecting whether a teleportation was successful.
What is the TeleportState?
When a teleportation request is made using TeleportService, there are a series of stages before the Player is teleported. The current stage is represented by the Enum.TeleportState value which is given by OnTeleport. See below for a practical example of this.
The summary of each of the TeleportStates in the documentation further highlight that it’s meant to be used in the context of detecting the current stage of the teleportation process that a player is at, before they have teleported to the new place. For reference, the InProgress stage, which was checked for in the third codeblock you posted, is described on the Roblox Creator Documentation site in the following way:
The teleport is currently in progress. The player usually disconnects and teleports to the destination after this.
With all of this in mind, I don’t think that player.OnTeleport can be used to detect when a player has arrived in a place as a result of a teleport (but since I haven’t tried that before, if I’m wrong about this, I’d be happy to be corrected via a video that showcases it working in a live game).
local teleportData = {
randomNumber = RNG:NextInteger(1, 100);
}
local teleportOptions = Instance.new("TeleportOptions")
teleportOptions:SetTeleportData(teleportData)
For the use case mentioned in the original post, the first example codeblock posted by @RobloxHasTalentR could be modified to make use of that TeleportOptions object:
Example server-sided code (to be included in the place that the player is leaving)
local TeleportService = game:GetService("TeleportService")
local targetPlaceId = 1 -- Place ID here
local function teleportPlayer(player)
local teleportData = {
arrivalPoint = "NameOfSpawnPoint"
-- Or
arrivalPoint = CFrame.new(0, 0, 0) -- Input desired coordinates
-- Refer to note at the bottom of this example codeblock for more info.
}
local teleportOptions = Instance.new("TeleportOptions")
teleportOptions:SetTeleportData(teleportData)
TeleportService:TeleportAsync(targetPlaceId, {player}, teleportOptions)
end
-- Call the "teleportPlayer" function when the player needs to be teleported
--[[
Note: If the player needs to be teleported to a completely
unique spawnpoint depending on the ride from the theme park that
they are exiting, this should probably be restructured so that you don't have
to duplicate the script over and over for each exit. Instead, all the intended
spawnpoints / CFrames could be kept in a single table (in a module, perhaps),
and then referenced from there. For a simple, smaller-scale solution, though,
including the example code above in individual scripts should suffice.
--]]
When detecting when players are arriving from a teleport in the new server, there are 2 main options that I am currently aware of:
Client-sided option
TeleportService.LocalPlayerArrivedFromTeleport – This event would fire on the client-side when the player arrives in the place as a result of the teleport. However, in the case of needing to retrieve the TeleportOptions, the documentation recommends the following:
Player:GetJoinData() returns a dictionary which includes the TeleportObject / teleportData that was sent through from the teleport. This is what will be referenced by the place that the player is being teleported to in order to determine where their Character model should be moved to upon joining.
Since you specifically mentioned that you wanted to teleport them to a CFrame upon arrival, I’ll structure the example code below in a way that checks for that as the incoming data rather than the name of a spawnpoint.
Example server-side code (to be included in the place that the player is arriving at, as a result of the teleport)
local Players = game:GetService("Players")
local function checkForTeleportData(player, Character)
local joinData = player:GetJoinData()
local teleportData = joinData["TeleportData"]
if teleportData ~= nil then
local arrivalPoint = TeleportData["arrivalPoint"]
if arrivalPoint ~= nil then
Character:PivotTo(arrivalPoint)
end
end
return false
end
local function onPlayerJoin(player)
local firstTimeJoin = true
if player.Character then
local returnValue = checkForTeleportData(player, player.Character)
firstTimeJoin = returnValue
end
player.CharacterAdded:Connect(function(Character)
if firstTimeJoin == true then
local returnValue = checkForTeleportData(player, Character)
firstTimeJoin = returnValue
end
--[[ Any other relevant code that you would want to run every time the
player's Character respawns would go here. --]]
end)
end
for _, player in Players:GetPlayers() do
task.spawn(onPlayerJoin, player)
end
Players.PlayerAdded:Connect(onPlayerJoin)
Hopefully all of this made sense; if you have any questions, feel free to ask and I’ll try to explain it more.
I know I’m late, but I’m kind of having the same situation here. What kind of scripts should the code be and where should each of them be inserted? (I don’t have much scripting knowledge, by the way)
All of the code is intended to be run on the server-side (since that is where Scripts have the authority to make changes that can be visible to all players in the game), which means that the code can be placed in a standard Script that has its RunContext property either set to the default of “Legacy” or “Server”.
When the RunContext is set to “Legacy”, the code within the Script can only run in certain places of the game (such as the Workspace and ServerScriptService) but if it’s set to “Server”, it can run in all containers that the server has access to (such as the ReplicatedStorage, ServerStorage, etc.)
The placement of each Script in the game doesn’t matter too much as long as it’s in a place where its code will be able to run. However, for organization purposes, I would recommend placing each one in the ServerScriptService.
Summary
In the game that the player is leaving
Code placed into a Script that has its RunContext property either set to the default of “Legacy” or “Server”. The Script can go in the ServerScriptService.
local TeleportService = game:GetService("TeleportService")
local targetPlaceId = 1 -- Place ID here
local function teleportPlayer(player)
local teleportData = {
arrivalPoint = "NameOfSpawnPoint"
-- Or
arrivalPoint = CFrame.new(0, 0, 0) -- Input desired coordinates
-- Refer to note at the bottom of this example codeblock for more info.
}
local teleportOptions = Instance.new("TeleportOptions")
teleportOptions:SetTeleportData(teleportData)
TeleportService:TeleportAsync(targetPlaceId, {player}, teleportOptions)
end
-- Call the "teleportPlayer" function when the player needs to be teleported
--[[
Note: If the player needs to be teleported to a completely
unique spawnpoint depending on the ride from the theme park that
they are exiting, this should probably be restructured so that you don't have
to duplicate the script over and over for each exit. Instead, all the intended
spawnpoints / CFrames could be kept in a single table (in a module, perhaps),
and then referenced from there. For a simple, smaller-scale solution, though,
including the example code above in individual scripts should suffice.
--]]
In the game that the player is being teleported to
Code placed into a Script that has its RunContext property either set to the default of “Legacy” or “Server”. The Script can go in the ServerScriptService.
local Players = game:GetService("Players")
local function checkForTeleportData(player, Character)
local joinData = player:GetJoinData()
local teleportData = joinData["TeleportData"]
if teleportData ~= nil then
local arrivalPoint = TeleportData["arrivalPoint"]
if arrivalPoint ~= nil then
Character:PivotTo(arrivalPoint)
end
end
return false
end
local function onPlayerJoin(player)
local firstTimeJoin = true
if player.Character then
local returnValue = checkForTeleportData(player, player.Character)
firstTimeJoin = returnValue
end
player.CharacterAdded:Connect(function(Character)
if firstTimeJoin == true then
local returnValue = checkForTeleportData(player, Character)
firstTimeJoin = returnValue
end
--[[ Any other relevant code that you would want to run every time the
player's Character respawns would go here. --]]
end)
end
for _, player in Players:GetPlayers() do
task.spawn(onPlayerJoin, player)
end
Players.PlayerAdded:Connect(onPlayerJoin)