roblox-teleport

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

roblox-teleport

roblox-teleport

Official sources:
TeleportService moves players between places and servers. The modern entry point is
TeleportAsync
(server-only); the older
Teleport
(client),
TeleportPartyAsync
,
TeleportToPlaceInstance
,
TeleportToPrivateServer
, and
TeleportToSpawnByName
methods are deprecated. Use
TeleportAsync()
instead. For client-initiated teleports, fire a
RemoteEvent
to the server and let the server call
TeleportAsync()
; do not call
Teleport()
from the client for new work, even if the place is configured as "Fully Open." See the migrate to secure teleports guide.
Cross-reference:
  • roblox-datastores/SKILL.md: handoff pattern for player data across teleports.
  • roblox-networking/SKILL.md: server authority, rate limiting, and the security model around teleport requests.
  • roblox-core/SKILL.md: services and script contexts.
官方来源:
TeleportService 可在 place 和 server 之间移动玩家。现代入口是
TeleportAsync
(仅限服务端);旧的
Teleport
(客户端)、
TeleportPartyAsync
、
TeleportToPlaceInstance
、
TeleportToPrivateServer
和
TeleportToSpawnByName
方法现已弃用。请改用
TeleportAsync()
。对于由客户端发起的传送,应由客户端触发
RemoteEvent
,再由服务端调用
TeleportAsync()
;新项目不要从客户端调用
Teleport()
,即使 place 的配置为「Fully Open」也一样。请参阅迁移到安全传送指南。
交叉参考:
  • roblox-datastores/SKILL.md:跨传送交接玩家数据的模式。
  • roblox-networking/SKILL.md:服务端权威、速率限制以及传送请求相关的安全模型。
  • roblox-core/SKILL.md:服务与脚本上下文。

Multi-place architecture

多 place 架构

A universe (experience) can contain multiple places. Each place has its own
PlaceId
; the universe has a
UniverseId
(exposed as
game.GameId
). The primary place is the one players join from the Roblox app's main entry point.
  • Create additional places in the Creator Dashboard under your experience → Places.
  • Each place must be published and (for it to be joinable) visible/enabled.
  • game.PlaceId
    is the current place;
    game.GameId
    is the universe ID (sometimes called UniverseId).
  • Places in the same universe share DataStores, MemoryStores, and Asset permissions.
  • Cross-universe (cross-experience) teleports are restricted by default. See "Cross-experience teleports" below.
一个 universe(experience)可以包含多个 place。每个 place 都有自己的
PlaceId
;universe 则拥有
UniverseId
(通过
game.GameId
暴露)。主 place 是玩家从 Roblox app 主入口加入的 place。
  • 在 Creator Dashboard 中进入你的 experience → Places,创建其他 place。
  • 每个 place 都必须已发布,并且(为了能够加入)设为可见和启用。
  • game.PlaceId
    是当前 place;
    game.GameId
    是 universe ID(有时也称为 UniverseId)。
  • 同一 universe 中的 place 共享 DataStores、MemoryStores 和 Asset 权限。
  • 跨 universe(跨 experience)传送默认受到限制。请参阅下文“跨 experience 传送”。

TeleportAsync (the modern method)

TeleportAsync(现代方法)

TeleportService:TeleportAsync(placeId, players, teleportOptions?)
is the single unified method. It can teleport to a different place, a specific server, or a reserved server. Server-only. Calling from the client errors.
Teleport()
and the other legacy methods now carry a deprecation message directing you to
TeleportAsync()
(see Teleport between places).
lua
--!strict
local TeleportService = game:GetService("TeleportService")
local Players = game:GetService("Players")

local DESTINATION_PLACE_ID = 1234567890

local function teleportToPlace(player: Player)
    local options = Instance.new("TeleportOptions")
    -- options.ServerInstanceId = "..." -- to target a specific server
    -- options.ReservedServerAccessCode = "..." -- to join a reserved server
    -- options.ShouldReserveServer = true -- to create+join a new reserved server
    options:SetTeleportData({ reason = "lobby_choice", mode = "classic" })

    local ok, result = pcall(function()
        return TeleportService:TeleportAsync(DESTINATION_PLACE_ID, { player }, options)
    end)
    if not ok then
        warn("TeleportAsync failed:", tostring(result))
        return false
    end
    -- result is a TeleportAsyncResult with info about the destination
    return true
end
TeleportService:TeleportAsync(placeId, players, teleportOptions?)
是统一入口。它可以传送到不同 place、特定 server 或 reserved server。仅限服务端。从客户端调用会报错。
Teleport()
及其他旧版方法现在都会显示弃用提示,并引导你使用
TeleportAsync()
(请参阅在不同 place 之间传送)。
lua
--!strict
local TeleportService = game:GetService("TeleportService")
local Players = game:GetService("Players")

local DESTINATION_PLACE_ID = 1234567890

local function teleportToPlace(player: Player)
    local options = Instance.new("TeleportOptions")
    -- options.ServerInstanceId = "..." -- to target a specific server
    -- options.ReservedServerAccessCode = "..." -- to join a reserved server
    -- options.ShouldReserveServer = true -- to create+join a new reserved server
    options:SetTeleportData({ reason = "lobby_choice", mode = "classic" })

    local ok, result = pcall(function()
        return TeleportService:TeleportAsync(DESTINATION_PLACE_ID, { player }, options)
    end)
    if not ok then
        warn("TeleportAsync failed:", tostring(result))
        return false
    end
    -- result is a TeleportAsyncResult with info about the destination
    return true
end

Group teleport limits

群体传送限制

  • Groups can only be teleported within a single experience (same universe).
  • Max 50 players per
    TeleportAsync
    call.
  • 群体只能在同一个 experience 内(同一 universe)传送。
  • 每次
    TeleportAsync
    调用最多传送 50 名玩家。

Conflicting TeleportOptions

冲突的 TeleportOptions

These combinations error with "Incompatible Parameters":
  • ReservedServerAccessCode
    +
    ServerInstanceId
  • ShouldReserveServer
    +
    ServerInstanceId
  • ShouldReserveServer
    +
    ReservedServerAccessCode
以下组合会报「Incompatible Parameters」错误:
  • ReservedServerAccessCode
    +
    ServerInstanceId
  • ShouldReserveServer
    +
    ServerInstanceId
  • ShouldReserveServer
    +
    ReservedServerAccessCode

TeleportOptions

TeleportOptions

PropertyPurpose
ServerInstanceId
Target a specific server by
JobId
.
ReservedServerAccessCode
Join an existing reserved server by its access code.
ShouldReserveServer
Create a new reserved server and teleport into it.
SetTeleportData(data)
/
GetTeleportData()
Pass data to the destination (retrieved via
GetLocalPlayerTeleportData
).
属性用途
ServerInstanceId
通过
JobId
指定目标 server。
ReservedServerAccessCode
使用访问码加入现有 reserved server。
ShouldReserveServer
创建新的 reserved server 并传送进去。
SetTeleportData(data)
/
GetTeleportData()
向目标位置传递数据(通过
GetLocalPlayerTeleportData
获取)。

TeleportAsyncResult

TeleportAsyncResult

When
TeleportOptions
is passed,
TeleportAsync
returns a
TeleportAsyncResult
with information about the final teleport destination. Useful for confirming where a player ended up.
传入
TeleportOptions
后,
TeleportAsync
会返回一个
TeleportAsyncResult
,其中包含最终传送目标的信息。该结果可用于确认玩家最终到达的位置。

TeleportInitFailed (error handling)

TeleportInitFailed(错误处理)

TeleportService.TeleportInitFailed
fires when a teleport fails to start. Connect to it to show a retry UI. Failure reasons include invalid place ID, empty player list, non-Player instances, wrong teleport options type, client-called
TeleportAsync
, and conflicting parameters.
lua
TeleportService.TeleportInitFailed:Connect(function(
    player: Player,
    reason: Enum.TeleportResult,
    errMsg: string,
    placeId: number,
    options: TeleportOptions
)
    warn(`Teleport failed for {player.Name} to {placeId}: {reason.Name} - {errMsg}`)
    -- Show retry UI, log options, etc.
end)
当传送无法启动时,
TeleportService.TeleportInitFailed
会触发。可以连接此事件来显示重试界面。失败原因包括 place ID 无效、玩家列表为空、实例不是 Player、传送选项类型错误、客户端调用
TeleportAsync
,以及参数冲突。
lua
TeleportService.TeleportInitFailed:Connect(function(
    player: Player,
    reason: Enum.TeleportResult,
    errMsg: string,
    placeId: number,
    options: TeleportOptions
)
    warn(`Teleport failed for {player.Name} to {placeId}: {reason.Name} - {errMsg}`)
    -- Show retry UI, log options, etc.
end)

Reserved servers

Reserved servers

TeleportService:ReserveServerAsync(placeId)
(server-only, yields) returns an access code plus a
PrivateServerId
. Players can only join a reserved server via that access code. They can't join through normal matchmaking.
  • A server starts when the access code is first used.
  • Access codes remain valid indefinitely; a reserved server can be rejoined even if no server is currently running (a new one starts).
  • Detect reserved-server context:
    local isReserved = game.PrivateServerId ~= "" and game.PrivateServerOwnerId == 0
    .
  • PrivateServerId
    is constant across server instances for the same access code;
    JobId
    is not.
  • Cross-platform caveat: Xbox/PlayStation players with cross-play disabled land in a different server than cross-play-enabled players. Multiple servers can share a
    PrivateServerId
    . Use
    game.MatchmakingType
    to differentiate.
lua
--!strict
local TeleportService = game:GetService("TeleportService")
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")

-- Reserve a candidate, then atomically publish-or-use the winner.
local store = DataStoreService:GetDataStore("ReservedServerAllocations_v2")
local reserveOk, candidateCode = pcall(function()
    return select(1, TeleportService:ReserveServerAsync(game.PlaceId))
end)
local code: string? = nil
if reserveOk and typeof(candidateCode) == "string" then
    local now = os.time()
    local candidate = { accessCode = candidateCode, expiresAt = now + 3600, state = "allocated" }
    local publishOk, winner = pcall(function()
        return store:UpdateAsync("DungeonRoom_1", function(current)
            if type(current) == "table" and type(current.accessCode) == "string" and current.expiresAt > now then
                return current
            end
            return candidate
        end)
    end)
    if publishOk and type(winner) == "table" then
        code = winner.accessCode -- every racing allocator uses the same winner
    end
end

local function sendToDungeon(player: Player)
    if not code then return end
    local options = Instance.new("TeleportOptions")
    options.ReservedServerAccessCode = code
    options:SetTeleportData({ room = 1 })
    pcall(function()
        TeleportService:TeleportAsync(game.PlaceId, { player }, options)
    end)
end
TeleportService:ReserveServerAsync(placeId)
(仅限服务端,执行时会 yield)会返回一个访问码和一个
PrivateServerId
。玩家只能通过该访问码加入 reserved server,无法通过常规 matchmaking 加入。
  • 首次使用访问码时,server 才会启动。
  • 访问码会无限期保持有效;即使当前没有正在运行的 server,也可以重新加入 reserved server(届时会启动一个新 server)。
  • 检测 reserved server 上下文:
    local isReserved = game.PrivateServerId ~= "" and game.PrivateServerOwnerId == 0
    。
  • 对于同一个访问码,
    PrivateServerId
    在不同 server 实例中保持不变;
    JobId
    则会变化。
  • **跨平台注意事项:**禁用 cross-play 的 Xbox/PlayStation 玩家会进入与启用 cross-play 的玩家不同的 server。多个 server 可以共享同一个
    PrivateServerId
    。请使用
    game.MatchmakingType
    进行区分。
lua
--!strict
local TeleportService = game:GetService("TeleportService")
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")

-- Reserve a candidate, then atomically publish-or-use the winner.
local store = DataStoreService:GetDataStore("ReservedServerAllocations_v2")
local reserveOk, candidateCode = pcall(function()
    return select(1, TeleportService:ReserveServerAsync(game.PlaceId))
end)
local code: string? = nil
if reserveOk and typeof(candidateCode) == "string" then
    local now = os.time()
    local candidate = { accessCode = candidateCode, expiresAt = now + 3600, state = "allocated" }
    local publishOk, winner = pcall(function()
        return store:UpdateAsync("DungeonRoom_1", function(current)
            if type(current) == "table" and type(current.accessCode) == "string" and current.expiresAt > now then
                return current
            end
            return candidate
        end)
    end)
    if publishOk and type(winner) == "table" then
        code = winner.accessCode -- every racing allocator uses the same winner
    end
end

local function sendToDungeon(player: Player)
    if not code then return end
    local options = Instance.new("TeleportOptions")
    options.ReservedServerAccessCode = code
    options:SetTeleportData({ room = 1 })
    pcall(function()
        TeleportService:TeleportAsync(game.PlaceId, { player }, options)
    end)
end

Passing data across teleports

跨传送传递数据

Two mechanisms, with different security profiles:
有两种机制,各自具有不同的安全特征:

TeleportOptions:SetTeleportData
/
GetLocalPlayerTeleportData

TeleportOptions:SetTeleportData
/
GetLocalPlayerTeleportData

Set on the source server (via
TeleportOptions
), retrieved on the destination client via
TeleportService:GetLocalPlayerTeleportData()
. Client-only retrieval. Can carry any serializable value.
Security: exploiters can spoof teleport data. Send sensitive data (currency, entitlements) through
DataStoreService
instead, and use teleport data only for non-sensitive hints (selected game mode, cosmetic loadout preference).
在源 server 上通过
TeleportOptions
设置数据,并在目标客户端通过
TeleportService:GetLocalPlayerTeleportData()
获取数据。**仅支持客户端读取。**可以携带任意可序列化值。
**安全性:**攻击者可以伪造传送数据。敏感数据(如货币、权益)应通过
DataStoreService
传输;传送数据只应用于非敏感提示信息,例如选定的游戏模式或外观装备偏好。

SetTeleportSetting
/
GetTeleportSetting

SetTeleportSetting
/
GetTeleportSetting

Client-only, stored locally, preserved across teleports within the same game. Good for client-side preferences (crouch state, UI tab) that don't need server trust. Also spoofable. Use server-side validation for anything that affects gameplay.
仅限客户端使用,数据保存在本地,并在同一 game 内的多次传送之间保留。适合不需要服务端信任的客户端偏好,例如蹲伏状态、UI 标签页。同样可以被伪造。任何会影响玩法的数据都应进行服务端验证。

Custom loading screen

自定义加载界面

TeleportService:SetTeleportGui(gui)
(client) sets a
ScreenGui
shown during teleport.
TeleportService:GetArrivingTeleportGui()
(client, at the destination) retrieves it so you can parent it to
PlayerGui
and run your own transition. The teleport GUI does not cross into a different game (universe), and does not persist across multiple teleports. Set it before each one.
lua
--!strict
-- At the destination, in ReplicatedFirst
local TeleportService = game:GetService("TeleportService")
local Players = game:GetService("Players")
local ReplicatedFirst = game:GetService("ReplicatedFirst")

local customLoadingScreen = TeleportService:GetArrivingTeleportGui()
if customLoadingScreen then
    local playerGui = Players.LocalPlayer:WaitForChild("PlayerGui")
    ReplicatedFirst:RemoveDefaultLoadingScreen()
    customLoadingScreen.Parent = playerGui
    task.wait(5)
    customLoadingScreen:Destroy()
end
TeleportService:SetTeleportGui(gui)
(客户端)可设置传送期间显示的
ScreenGui
。
TeleportService:GetArrivingTeleportGui()
(客户端,在目标端)用于获取该界面,随后可以将其挂载到
PlayerGui
并运行自定义过渡动画。传送 GUI 不会被带入另一个 game(universe),也不会在连续多次传送之间保留。每次传送前都需要重新设置。
lua
--!strict
-- At the destination, in ReplicatedFirst
local TeleportService = game:GetService("TeleportService")
local Players = game:GetService("Players")
local ReplicatedFirst = game:GetService("ReplicatedFirst")

local customLoadingScreen = TeleportService:GetArrivingTeleportGui()
if customLoadingScreen then
    local playerGui = Players.LocalPlayer:WaitForChild("PlayerGui")
    ReplicatedFirst:RemoveDefaultLoadingScreen()
    customLoadingScreen.Parent = playerGui
    task.wait(5)
    customLoadingScreen:Destroy()
end

Cross-experience teleports

跨 experience 传送

Teleporting from your experience to another experience owned by others fails by default. To enable cross-experience teleportation, follow the steps in the official Teleport between places doc. Within your own universe (cross-place), teleports work without extra setup.
TeleportService:PromptExperienceDetailsAsync(player, universeId)
(client-only, yields) prompts the player with experience details and a Join button. If the player is ineligible to join the target experience, the button is disabled. The join button is always disabled during Studio playtesting.
从你的 experience 传送到由其他人拥有的另一个 experience时,默认会失败。要启用跨 experience 传送,请按照官方在不同 place 之间传送文档中的步骤操作。在你自己的 universe 内(跨 place)传送,无需额外设置即可正常工作。
TeleportService:PromptExperienceDetailsAsync(player, universeId)
(仅限客户端,执行时会 yield)会向玩家显示 experience 详情和 Join 按钮。如果玩家没有资格加入目标 experience,该按钮会被禁用。在 Studio 中试玩时,Join 按钮始终处于禁用状态。

Matchmaking patterns

Matchmaking 模式

Pattern 1: lobby → match (simple round-robin)

模式 1:lobby → match(简单轮询调度)

A lobby place collects players; when enough are ready,
TeleportAsync
sends them to a game place. Use
MessagingService
to coordinate across lobby servers if you have multiple lobbies.
lobby place 负责收集玩家;当足够数量的玩家准备就绪后,使用
TeleportAsync
将他们传送到游戏 place。如果有多个 lobby server,可以使用
MessagingService
在这些 server 之间进行协调。

Pattern 2: reserved server per match

模式 2:每场比赛使用一个 reserved server

For instanced dungeons or private matches:
ReserveServerAsync
→ persist the access code in a DataStore keyed by match ID → teleport the party with
ReservedServerAccessCode
→ players arrive in an isolated server.
对于实例化副本或私人比赛:调用
ReserveServerAsync
→ 将访问码持久化到以比赛 ID 为键的 DataStore → 使用
ReservedServerAccessCode
传送整个队伍 → 玩家进入相互隔离的 server。

Pattern 3: server browser via MemoryStoreService

模式 3:通过 MemoryStoreService 实现服务器浏览器

Maintain a
MemoryStoreService
sorted map of active servers (keyed by
JobId
, value = player count / mode / ping). The lobby lists entries; when a player picks one,
TeleportOptions.ServerInstanceId = jobId
and
TeleportAsync
. Update the sorted map from each game server on join/leave. This scales better than
MessagingService
for many servers.
维护一个
MemoryStoreService
sorted map,用于记录活跃 server(以
JobId
为键,值为玩家数量/模式/延迟)。lobby 列出这些条目;玩家选择一个条目后,设置
TeleportOptions.ServerInstanceId = jobId
并调用
TeleportAsync
。每个游戏 server 在玩家加入或离开时更新该 sorted map。在 server 数量较多时,这种方式比
MessagingService
扩展性更好。

Pattern 4: external matchmaking service

模式 4:外部 matchmaking 服务

For complex matchmaking (skill-based, party queues), use an external HTTP service as the matchmaker. It returns a
placeId
+
JobId
or a fresh reserved-server access code; the lobby then
TeleportAsync
s the party. See roblox-networking for the
HttpService
security model and roblox-open-cloud for in-experience Open Cloud calls.
All matchmaking must respect the 50-player-per-
TeleportAsync
limit; split larger groups into multiple calls.
对于复杂的 matchmaking(基于技能分、组队队列),可使用外部 HTTP 服务作为匹配器。该服务返回
placeId
+
JobId
,或一个全新的 reserved server 访问码;随后 lobby 使用
TeleportAsync
传送队伍。有关
HttpService
安全模型,请参阅 roblox-networking;有关 experience 内的 Open Cloud 调用,请参阅 roblox-open-cloud。
所有 matchmaking 都必须遵守每次
TeleportAsync
最多 50 名玩家
的限制;更大的群体需要拆分为多次调用。

DataStore handoff across teleports

跨传送进行 DataStore 交接

To move player state between places:
  1. Source server: on the triggering event, save the player's profile via
    UpdateAsync
    (see roblox-datastores). Then teleport.
  2. Destination server: on
    PlayerAdded
    , load the profile via
    GetAsync
    (consider
    UseCache=false
    for a fresh read if the save was recent).
  3. Race condition: if the save hasn't flushed by the time the destination loads, you'll get stale data. Mitigate by: (a) awaiting save confirmation before teleporting when the data is critical, or (b) passing a "load this version" hint in teleport data and retrying the load until it matches.
  4. Never trust teleport data for the authoritative state. Teleport data is a hint; the DataStore is the truth.
要在不同 place 之间移动玩家状态:
  1. **源 server:**在触发事件时,通过
    UpdateAsync
    保存玩家档案(参见 roblox-datastores),然后再执行传送。
  2. **目标 server:**在
    PlayerAdded
    时,通过
    GetAsync
    加载玩家档案(如果保存时间较近,可考虑使用
    UseCache=false
    以获取最新数据)。
  3. **竞态条件:**如果目标端加载时源端的保存尚未完成同步,就会读取到过期数据。可以通过以下方式缓解:(a) 对关键数据,在传送前等待保存确认;或 (b) 在传送数据中传递「加载此版本」提示,并重试加载直到版本匹配。
  4. **永远不要将传送数据视为权威状态。**传送数据只是提示,DataStore 才是事实来源。

Security

安全性

  • TeleportAsync
    is server-only.
    The client cannot call it directly. If you need client-initiated teleports, the client sends a RemoteEvent and the server validates then calls
    TeleportAsync
    . The legacy client method
    Teleport()
    is now deprecated (use
    TeleportAsync()
    on the server); see the migration guide above.
  • Rate-limit teleport requests per player. A hostile client spamming "teleport me" Remotes can disrupt your server flow and burn DataStore budget if you save on each trigger.
  • Validate the destination. Don't let a client-supplied place ID drive the teleport unsanitized. Whitelist allowed destinations server-side.
  • Teleport data is spoofable. Treat it as a hint; re-validate any gameplay-affecting claim on the destination server against DataStores.
  • GetLocalPlayerTeleportData
    is client-only
    and returns client-controlled data. Don't use it for authoritative decisions on the server.
  • **
    TeleportAsync
    仅限服务端。**客户端不能直接调用。如果需要由客户端发起传送,应让客户端发送
    RemoteEvent
    ,再由服务端验证并调用
    TeleportAsync
    。旧版客户端方法
    Teleport()
    已弃用,请在服务端使用
    TeleportAsync()
    ;请参阅前述迁移指南。
  • **按玩家限制传送请求频率。**恶意客户端持续发送「传送我」的 Remote 事件,可能扰乱服务器流程;如果每次触发都保存数据,还会消耗 DataStore 配额。
  • **校验传送目标。**不要让客户端提供且未经清理的 place ID 直接驱动传送。应在服务端使用允许列表限制可传送的目标。
  • **传送数据可以被伪造。**应将其视为提示;目标 server 上任何会影响玩法的声明都必须使用 DataStores 重新验证。
  • GetLocalPlayerTeleportData
    仅限客户端使用
    ,且返回的数据由客户端控制。不要在服务端将其用于权威决策。

Studio limitation

Studio 限制

TeleportService does not work during Studio playtesting. You must publish the experience and test teleports in the Roblox application. Plan for this in your testing workflow. Teleport logic can only be verified live.
**TeleportService 在 Studio 试玩期间无法工作。**必须先发布 experience,然后在 Roblox app 中测试传送。请在测试工作流中为此做好规划。传送逻辑只能在正式线上环境中验证。

Gotchas

常见陷阱

  • Players lose character state across teleports (new place = new character). Save/load via DataStores; don't try to carry live character state.
  • BindToClose
    on the source server can race with the teleport. Finish saves before triggering teleports when data is critical.
  • The default teleport loading message was removed;
    CustomizedTeleportUI
    is deprecated and does nothing.
  • Cross-platform (Xbox/PS with cross-play off) can split a reserved server into multiple servers with the same
    PrivateServerId
    .
  • Group teleports are universe-only; you cannot
    TeleportAsync
    a group across experiences.
  • The 50-player limit is per call. Larger groups need multiple calls, and ordering matters for "arrive together" semantics.
  • Follow-friend:
    Players.PlayerAdded
    → check
    player.FollowUserId
    →
    GetPlayerPlaceInstanceAsync(followId)
    →
    TeleportToPlaceInstance
    . Note
    GetPlayerPlaceInstanceAsync
    returns
    JobId
    , not the reserved-server access code, so it won't work to follow a friend into a reserved server.
  • 玩家跨传送后会丢失角色状态(进入新 place 会生成新角色)。应通过 DataStores 保存和加载数据,不要尝试直接携带实时角色状态。
  • 源 server 上的
    BindToClose
    可能与传送发生竞态。关键数据应先完成保存,再触发传送。
  • 默认传送加载消息已被移除;
    CustomizedTeleportUI
    已弃用且不会执行任何功能。
  • 跨平台场景(Xbox/PS 关闭 cross-play)可能将一个 reserved server 拆分为多个具有相同
    PrivateServerId
    的 server。
  • 群体传送只能在同一 universe 内进行;不能使用
    TeleportAsync
    将群体传送到其他 experience。
  • 50 名玩家的限制针对每次调用。更大的群体需要多次调用,并且调用顺序会影响“一起到达”的效果。
  • 跟随好友:
    Players.PlayerAdded
    → 检查
    player.FollowUserId
    →
    GetPlayerPlaceInstanceAsync(followId)
    →
    TeleportToPlaceInstance
    。请注意,
    GetPlayerPlaceInstanceAsync
    返回的是
    JobId
    ,而不是 reserved server 访问码,因此无法用于跟随好友进入 reserved server。

Scripts

脚本

  • scripts/TeleportHelper.lua
    : a reviewed server-side example with atomic reserved-code publication, expiry, ambiguous-allocation reconciliation, and separate
    teleporting
    /
    arrived
    states.
  • scripts/TeleportHelper.lua
    :一个经过审查的服务端示例,包含 reserved code 的原子发布、过期处理、歧义分配协调,以及相互独立的
    teleporting
    /
    arrived
    状态。

How to proceed

后续步骤

  1. Decide your place architecture: primary place + sub-places in one universe.
  2. For cross-place teleports, use
    TeleportAsync
    (server) +
    TeleportOptions
    .
  3. For reserved servers, reserve a candidate and publish it through
    UpdateAsync
    ; use whichever allocation wins. Track teleport initiation separately from destination arrival.
  4. Pass non-sensitive hints via teleport data; pass authoritative state via DataStores.
  5. Connect
    TeleportInitFailed
    for retry UI.
  6. Validate and rate-limit any client-initiated teleport Remote.
  7. Test in the Roblox app (not Studio) with a published experience.
<!-- catalog:references:start -->
  1. 确定 place 架构:主 place + 同一 universe 内的子 place。
  2. 对于跨 place 传送,使用
    TeleportAsync
    (服务端)+
    TeleportOptions
    。
  3. 对于 reserved server,先预留候选 server,并通过
    UpdateAsync
    发布;使用最终胜出的分配结果。将传送发起与目标端到达分开跟踪。
  4. 通过传送数据传递非敏感提示信息;通过 DataStores 传递权威状态。
  5. 连接
    TeleportInitFailed
    ,以显示重试界面。
  6. 对任何由客户端发起的传送 Remote 进行验证和速率限制。
  7. 在 Roblox app 中(而非 Studio 中)使用已发布的 experience 进行测试。
<!-- catalog:references:start -->

Reference index

参考索引

  • matchmaking.md: Coordinate lobbies, reserved servers, allocation races, or player-data handoff.
  • teleport-options.md: Select a destination server or inspect a teleport result.
<!-- catalog:references:end -->
  • matchmaking.md:协调 lobby、reserved server、分配竞态或玩家数据交接。
  • teleport-options.md:选择目标 server 或检查传送结果。
<!-- catalog:references:end -->