在地点之间传送

*此内容使用人工智能(Beta)翻译,可能包含错误。若要查看英文页面,请点按 此处

许多游戏被划分为多个 地点,例如一个有城镇、城堡、地下城和广阔森林的幻想世界。使用 TeleportService 在地点之间、在不同服务器之间,甚至在其他游戏之间传送用户。

传送玩家

要传送玩家,使用 TeleportService:TeleportAsync()。此方法接受三个参数:


local Players = game:GetService("Players")
local TeleportService = game:GetService("TeleportService")
local TARGET_PLACE_ID = 12345678901234 -- 替换为你自己的
local playerToTeleport = Players:GetPlayers()[1] -- 获取游戏中的第一个用户
TeleportService:TeleportAsync(TARGET_PLACE_ID, {playerToTeleport})

要获取要传送的适当玩家,你可以使用 BasePart.TouchedProximityPrompt.Triggered 事件来获取单个 Player。然后你可以检查玩家是否属于某个团队 (Player.Team) 或派对 (Player.PartyId)。最后,如果你想传送整个小组而不仅仅是个人,可以使用 Team:GetPlayers()SocialService:GetPlayersByPartyId()

配置安全传送

三个设置处理传送安全性。

设置描述
(创建者仪表板) 受众 > 访问设置 > 地点访问控制控制玩家是否可以通过任何游戏加入你游戏中的任何地点,或者必须先加入 起始地点
(创建者仪表板) 地点 > 访问 > 直接访问控制为非起始地点覆盖你的游戏级 地点访问控制 设置。
(Studio) 文件 > 体验设置 > 安全性 > 允许第三方传送控制从你的游戏到 你不拥有的游戏 的传送。你可以保持此设置为禁用,并仍然在你拥有的已发布游戏之间传送玩家。

地点访问控制 控制玩家传送 进入 你的游戏,并且是防止基于传送的漏洞的最关键设置。

创建者中心的地点访问控制

  • 如果你选择 完全开放,玩家可以通过任何游戏的传送加入你游戏中的任何地点,包括深层链接、游戏邀请、加入朋友等。

    如果你的游戏有多个地点,并且你想让朋友们能够轻松地加入彼此,无论他们在哪个地点,这是一个不错的选择。如果你不选择此选项,尝试在非起始地点加入朋友的玩家将会进入你游戏的起始地点。

  • 如果你选择 限制为同一宇宙,玩家只能通过你游戏内的传送加入非起始地点。此设置允许客户端和服务器发起的传送。

    如果你有一款你不想 迁移到安全传送 的遗留游戏,这是一个不错的选择。

  • 如果你选择 仅在宇宙内安全,玩家只能通过在此游戏内发起的服务器传送加入非起始地点。

    如果你的游戏有严格的进度系统,在玩家可以访问某些区域之前,这是一个不错的选择。如果你的游戏有一个玩家不应该访问的测试地点,或者仅使用保留服务器的地点,这也是一个不错的选择。

迁移到安全传送

如果你有一款现有的使用客户端传送的游戏,并希望强制要求服务器发起的传送,目标是将所有传送逻辑从客户端脚本移动到服务器脚本:

  1. 找到所有调用 Teleport() 的客户端脚本。
  2. 将这些调用改为触发 远程事件。或者,你可以修改这些调用,改为使用 ProximityPromptsClickDetectors,甚至仅使用 BasePart.Touched 事件。
  3. 使用 TeleportAsync() 在服务器脚本中重新实现传送。
  4. 当不再存在 Teleport() 调用时,将 地点访问控制 改为 安全

创建自定义传送屏幕

当用户触发传送时,他们会看到标准的 Roblox 加载屏幕,等待新地点加载。如有需要,你可以通过在客户端调用 TeleportService:SetTeleportGui() 添加一个自定义传送屏幕。

以下示例从 ReplicatedStorage 设置一个自定义的 ScreenGuiScreenGui 内的任何脚本都 不会 运行。


local TeleportService = game:GetService("TeleportService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local teleportGui = ReplicatedStorage.TeleportGui
TeleportService:SetTeleportGui(teleportGui)

自定义传送选项

你可以通过设置 TeleportOptions 实例并将其传递给 TeleportService:TeleportAsync() 方法来自定义传送,例如 将用户传送到特定服务器在传送中发送用户数据

传送到特定服务器

要将用户传送到特定服务器,请使用 TeleportOptions 设置目标服务器并将其传递给 TeleportAsync() 方法。如果你未指定服务器,用户将被传送到公共服务器;此列表中第一个用户的信息将用于匹配。

要将用户传送到特定的公共服务器,请将 TeleportOptions.ServerInstanceId 属性设置为有效的实例 ID,这是公共服务器的唯一标识符。


local teleportOptions = Instance.new("TeleportOptions")
teleportOptions.ServerInstanceId = targetServerId

要将用户传送到特定的保留服务器,请设置有效的 TeleportOptions.ReservedServerAccessCode,这是进入保留服务器的唯一代码。


local teleportOptions = Instance.new("TeleportOptions")
teleportOptions.ReservedServerAccessCode = reservedServerCode

要将用户传送到新的保留服务器,请将 TeleportOptions.ShouldReserveServer 设置为 true。


local teleportOptions = Instance.new("TeleportOptions")
teleportOptions.ShouldReserveServer = true

在传送中发送用户数据

在地方之间传送用户会丢弃与该用户相关的任何本地数据。你可以使用以下方法处理地方之间的数据持久性:

  • 如果你的游戏使用 安全 用户数据,如游戏内货币或库存,请实现 数据存储内存存储,以保持数据在地方之间的迁移。

  • 要从地方之间发送基本的 非安全 数据,请在传递给 TeleportAsync() 之前调用 TeleportOptions:SetTeleportData()请不要 使用此方法传递安全数据;数据对客户端可见且未加密。


local teleportData = {
randomNumber = RNG:NextInteger(1, 100),
}
local teleportOptions = Instance.new("TeleportOptions")
teleportOptions:SetTeleportData(teleportData)

要在用户传送到新地点后检索所有数据,请使用 Player:GetJoinData() 函数,其返回一个字典,包含一个 TeleportData 键。


local Players = game:GetService("Players")
local function onPlayerAdded(player)
local joinData = player:GetJoinData()
local teleportData = joinData.TeleportData
local randomNumber = teleportData.randomNumber
print(player.Name .. " 以数字 " .. randomNumber .. " 加入")
end
Players.PlayerAdded:Connect(onPlayerAdded)

要仅在客户端检索传送数据,可以使用 TeleportService:GetLocalPlayerTeleportData()

处理失败的传送

像任何涉及网络请求的 API 调用,传送可能会失败并抛出错误。将它们包裹在保护调用中 (pcall())。一些失败需要重试,特别是涉及保留服务器的失败,因此我们建议在失败时重试若干次。

即使调用成功并且传送启动,它仍然可能在最后一刻失败而不抛出错误,并将用户留在服务器上。当这种情况发生时,会触发 TeleportService.TeleportInitFailed 事件。

以下示例 ModuleScript 返回一个单独的 SafeTeleport 函数,该函数使用重试逻辑在保护调用中传送玩家。它还具有一个 handleFailedTeleport 函数,用于处理调用成功但未发生传送的情况。


local TeleportService = game:GetService("TeleportService")
local ATTEMPT_LIMIT = 5
local RETRY_DELAY = 1
local FLOOD_DELAY = 15
local function SafeTeleport(placeId, players, options)
local attemptIndex = 0
local success, result -- 在循环外定义 pcall 结果,以便稍后可以报告结果
repeat
success, result = pcall(function()
return TeleportService:TeleportAsync(placeId, players, options) -- 在保护调用中传送用户以防止出错
end)
attemptIndex += 1
if not success then
task.wait(RETRY_DELAY)
end
until success or attemptIndex == ATTEMPT_LIMIT -- 如果调用成功,或者达到重试限制,则停止尝试传送
if not success then
warn(result) -- 将失败原因打印到输出
end
return success, result
end
local function handleFailedTeleport(player, teleportResult, errorMessage, targetPlaceId, teleportOptions)
if teleportResult == Enum.TeleportResult.Flooded then
task.wait(FLOOD_DELAY)
elseif teleportResult == Enum.TeleportResult.Failure then
task.wait(RETRY_DELAY)
else
-- 如果传送无效,报告错误而不是重试
error(("无效的传送 [%s]: %s"):format(teleportResult.Name, errorMessage))
end
SafeTeleport(targetPlaceId, {player}, teleportOptions)
end
TeleportService.TeleportInitFailed:Connect(handleFailedTeleport)
return SafeTeleport

SafeTeleport 函数接收与 TeleportAsync() 函数相同的参数。你可以使用以下脚本与 SafeTeleport 函数一起从游戏的任何地方执行传送:


local Players = game:GetService("Players")
local TeleportService = game:GetService("TeleportService")
local ServerScriptService = game:GetService("ServerScriptService")
local SafeTeleport = require(ServerScriptService.SafeTeleport)
local PLACE_TO_TELEPORT_TO = 12345678
local function teleport(touchPart)
local playerToTeleport = game.Players:GetPlayerFromCharacter(touchPart.Parent)
if playerToTeleport then
SafeTeleport(PLACE_TO_TELEPORT_TO, {playerToTeleport})
end
end
script.Parent.Touched:Connect(teleport)
©2026 Roblox Corporation、Roblox、Roblox 标志及 Powering Imagination 是我们在美国及其他国家或地区的注册与未注册商标。