在地点之间传送

*此内容使用人工智能(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 是我们在美国及其他国家或地区的注册与未注册商标。