在服务器权威模型中,服务器是整个游戏状态的唯一真相来源,客户端只能被信任地报告自己的输入。这种架构是公平竞争游戏的核心网络代码基础,因为它通过绝不信任客户端报告其自身的位置或状态来防止全类作弊,比如飞行挂或加速挂。
优势
在一个简单的服务器拥有的系统中,客户端会将自己的输入发送到服务器,然后显示服务器返回的游戏结果。虽然从技术上讲是正确的,但这样的系统会面临重大的输入延迟,因为每个玩家的操作都必须发送到服务器,处理后再将结果发送回客户端,以便显示。对于大多数游戏,尤其是节奏快速的游戏,这种往返延迟会导致游戏玩法显得迟滞、不响应,并且无法玩。
在 Roblox 的服务器权威模型中,通过让客户端立即预测其输入的效果来补偿延迟,此外还将这些输入发送到服务器。例如,当玩家按下一个键时,客户端不会等待服务器的响应;相反,它会预测距离上一个已知的服务器状态几帧。这使得客户端能够立即显示输入操作的结果,有效地隐藏了网络延迟,使游戏感觉响应迅速。
有时候,客户端会预测错误(预测失误),由于网络延迟,客户端在几帧内不会知道自己犯了错误。例如:
当检测到预测失误时,客户端必须根据服务器的权威状态来纠正其预测。如果权威状态与客户端的预测状态不同,客户端必须回滚并重新模拟其预测的帧。这个客户端预测、回滚和重新模拟的系统被称为“延迟补偿”,有助于让服务器权威的多人游戏感觉平滑而敏捷。
设置
由于服务器权威模型需要某些其他引擎技术正常运行,因此您必须首先在资源管理器中将以下属性设置在Workspace对象上:
- Workspace.AuthorityMode必须为Server(以上所有必须首先设置)
概念
服务器权威系统基于几个核心概念,具体如下。
客户端预测
通过客户端预测,客户端在上一个已知服务器状态的基础上模拟几帧,以立即预测玩家输入的效果。这隐藏了输入延迟,但预测可能会在后期被证明是不正确的(客户端预测失误),因此需要纠正。客户端尝试模拟得刚好超前于上一个已知的权威服务器状态,以使其输入在预期的帧上到达服务器。客户端在已知服务器状态后预测的帧数是基于客户端和服务器之间的延迟。
客户端预测失误
当客户端接收到来自服务器的权威状态时,它会将该状态与其对该帧的本地预测的历史记录进行检查。当客户端预测的内容与服务器实际执行的内容之间存在差异时,这就是预测失误。预测失误可能由于多种原因发生,包括网络延迟的波动、其他玩家行为出乎客户端的意料、游戏在服务器上独占运行某些逻辑等。
如果权威状态与客户端的预测状态不同,客户端必须回滚并重新模拟。
回滚和重新模拟
当客户端检测到一个预测失误时,它必须重置为服务器的权威状态,然后重新模拟以跳回其预测的帧。根据网络延迟,客户端尝试在上一个已知的权威服务器状态基础上超前模拟,以便其输入在预期的帧到达服务器。
总之,客户端:
- 接收来自服务器的权威状态并与其自己的预测状态进行比较。
- 如果客户端的预测不正确:
- 客户端回滚到从服务器接收到的最后已知权威状态。
- 客户端从权威状态重新模拟到预测状态,重新应用任何本地输入。
实现
网络拥有权和预测
在服务器权威模型中,您可以保持核心游戏对象服务器拥有,同时不承担通常与服务器拥有相关的输入延迟成本。诸如汽车、玩家角色或其他关键游戏对象,即使在与其他玩家互动时也可以保持服务器拥有。
默认情况下,Roblox 将自动预测与本地玩家Character附近的仿真访问相关的属性,但如果您想要更细粒度的控制,可以使用RunService:SetPredictionMode()显式强制实例的预测开启或关闭。
仿真同步
在服务器权威模型中,客户端和服务器必须同时运行核心仿真,并且客户端的仿真需要能够在发生预测失误时进行回滚和重新模拟。为了实现这一点,请在绑定到RunService:BindToSimulation()的函数中编写您的核心逻辑,位于在客户端和服务器上初始化的ModuleScript中。

在重新模拟过程中,Roblox 将通过BindToSimulation()重新运行绑定到仿真的函数。处理玩家输入、与同步的物理对象交互以及更新核心游戏状态应在那些绑定的函数内进行。
ModuleScript命名为Simulation在ReplicatedStorage中:
Simulation
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local Simulation = {}
Simulation.Initialize = function()
RunService:BindToSimulation(function(deltaTime)
-- 读取玩家输入
-- 更新游戏状态
end)
end
return Simulation
属性同步
Roblox 自动同步所有与仿真访问有关的属性到预测实例。对于自定义数据,[属性s](/studio/properties#实例属性)是将标记为预测的实例同步的主要方式;在此类实例中,服务器的真相来源与客户端的预测之间的任何属性值不匹配将触发完整的回滚和重新模拟。
属性限制
为了能够被复制,属性必须满足以下所有标准:
- 它是在其Instance上的前 64 个属性之一。
- 它的名称最多包含 50 个字符。
- 如果是字符串类型属性,其值最多包含 50 个字符。
仿真访问
引擎 API 参考中的许多属性和方法包含仿真访问标签,例如BasePart.CFrame。带有此标签的属性将被服务器权威系统预测。此外,只有带有此标签的属性和方法可以在通过RunService:BindToSimulation()绑定的函数内部访问。
输入操作
在服务器权威游戏中,客户端影响游戏状态的主要方式是通过输入操作系统。这些输入被发送到服务器,并在客户端的重新模拟期间回放。因此,InputActions应用于所有影响核心仿真的输入,并且在处理之前应该进行合理性检查。
请注意,InputContexts必须是Player的一个子项,以便引擎知道谁拥有该InputContext。一种方法是将您的InputContexts添加到ReplicatedStorage下的一个文件夹中,并使用Script在ServerScriptService下克隆每个玩家的InputContexts:

InputSetup
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local InputsFolder = ReplicatedStorage:WaitForChild("Inputs")
local function onPlayerAdded(player)
local clone = InputsFolder:Clone()
clone.Parent = player
end
Players.PlayerAdded:Connect(onPlayerAdded)
for _, player in Players:GetPlayers() do
onPlayerAdded(player)
end
使用这种模式,您可以在客户端和服务器的RunService:BindToSimulation()中读取InputActions,以接收给定帧的相同数据,并将前一帧的输入记录在一个属性中,例如在触发RunAction输入操作时触发角色的奔跑。
请注意,如果您需要将自定义数据写入输入操作系统,应使用连接到RunService.RenderStepped或RunService:BindToRenderStep()的函数,而不是RunService:BindToSimulation()。在BindToSimulation()中触发一个InputAction可能会导致客户端在重新模拟期间生成不正确的结果。
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")
RunService:BindToRenderStep("CameraInput", Enum.RenderPriority.Last.Value, function()
-- 通过输入操作将客户端相机的前向向量发送到服务器
local cameraForwardInputAction = Players.LocalPlayer.PlayContext.CameraForward
local cameraForwardVector = Workspace.CurrentCamera.CFrame.LookVector
cameraForwardInputAction:Fire(cameraForwardVector)
end)
远程事件
远程事件仍可以在服务器权威模型中使用,以便促进客户端和服务器之间的离散通信。例如,服务器可以使用远程事件广播关于玩家得分或拾取物品的数据,客户端可以使用远程事件作为向服务器发送输入的替代 API,例如按下按钮或点击 3D 世界中的物体。
动画、声音和效果
客户端效果如动画和声音必须在知道客户端仿真仅是权威服务器状态预测的情况下编写。BindToSimulation()限制从绑定函数内部可以调用的属性和方法,以帮助指导您仅写入同步的仿真状态。展示此仿真的结果、触发效果和声音等应在连接到RenderStepped的单独函数中完成,该函数读取仿真的结果并触发所需的效果。
有关渲染预测仿真的进一步指导,请参见高级技术指南。
示例项目
除了本文件外,以下模板可以帮助您入门:


