伺服器權威模型

*此內容是使用 AI(Beta 測試版)翻譯,可能含有錯誤。若要以英文檢視此頁面,請按一下這裡

伺服器權威模型中,伺服器是整個遊戲狀態的唯一真相來源,而客戶端僅被信任報告自己的輸入。這種架構是公平競技遊戲的核心網路代碼基礎,因為它防止了類型的作弊行為,例如飛行作弊或速度作弊,因為永遠不會信任客戶端報告自己的位置或狀態。

優勢

在一個天真的伺服器擁有的系統中,客戶端將簡單地將其輸入發送到伺服器並顯示伺服器返回的遊戲結果。雖然在技術上是正確的,但這樣的系統會面臨顯著的輸入延遲,因為每個玩家的行動必須傳送到伺服器,經過處理,然後將結果發送回客戶端,才能顯示出來。對於大多數遊戲,尤其是那些快節奏的遊戲,這種來回延遲會使遊戲玩法感覺延遲、不響應且無法遊玩。

在 Roblox 的伺服器權威模型中,延遲通過讓客戶端瞬間預測其輸入的效果來進行補償,同時將它們發送到伺服器。例如,當玩家按下某個鍵時,客戶端不會等待伺服器的回應;相反,它會預測幾幀之後的上次已知伺服器狀態。這使得客戶端能夠立即顯示輸入行動的結果,有效地隱藏網路延遲,讓遊戲感覺響應靈敏。

有時,客戶端會錯誤地預測結果(錯誤預測),並且因為網路延遲,客戶端在幾幀內不會知道它出錯了。例如:

當檢測到錯誤預測時,客戶端必須根據伺服器的權威狀態來修正其預測。如果權威狀態與客戶端的預測狀態不同,客戶端必須回滾並重新模擬其預測的幀。這種客戶端預測、回滾和重新模擬的系統被稱為“延遲補償”,有助於使伺服器權威的多人遊戲感覺平滑且靈敏。

設置

由於伺服器權威模型需要某些其他引擎技術才能正確運行,您必須首先在Explorer中的Workspace物件上設置以下屬性:

  1. Workspace.AuthorityMode必須為Server(上述所有項目必須先設置)

概念

伺服器權威系統運行於幾個核心概念如下。

客戶端預測

透過客戶端預測,客戶端在已知的伺服器狀態的幾個幀之前進行模擬,以立即預測玩家輸入的效果。這隱藏了輸入延遲,但預測可能在後來證明是錯誤的(客戶端錯誤預測),因此需要更正。客戶端試圖只模擬到足夠接近的距離已知的權威伺服器狀態,以便其輸入在預定幀上到達伺服器。客戶端會在已知伺服器狀態的幀數根據客戶端和伺服器之間的延遲進行預測。

客戶端錯誤預測

當客戶端從伺服器接收權威狀態時,它將該狀態與其對該幀的本地預測的歷史記錄進行檢查。當客戶端預測和伺服器實際執行之間存在差異時,這被稱為錯誤預測。錯誤預測可能由幾個原因引起,包括網路延遲的變化、其他玩家採取客戶端未預見的行為、遊戲在伺服器上獨占運行某些邏輯等。

如果權威狀態與客戶端的預測狀態不同,客戶端必須回滾並重新模擬

回滾和重新模擬

當客戶端檢測到錯誤預測時,它必須重置為伺服器的權威狀態,然後重新模擬以跳回其預測的幀。根據網路延遲,客戶端試圖在已知的權威伺服器狀態的幾幀之前進行模擬,以便其輸入在預定的幀到達伺服器。

在上面的圖中,客戶端正在模擬伺服器的2幀之前。它為幀3發送其輸入,這些輸入在伺服器上按預定幀(3)到達。伺服器發送幀3的權威狀態,而客戶端在幀7接收到該狀態。客戶端發現它錯誤預測了幀3,因此它重置為伺服器的幀3,並在模擬幀4、5和6之前進行重新模擬。玩家可能會看到明顯的網路伪影,例如突然的移動。

總結來說,客戶端

  1. 接收來自伺服器的權威狀態並將其與自己的預測狀態進行比較。
  2. 如果客戶端的預測不正確:
    1. 客戶端回滾到從伺服器接收到的最後已知的權威狀態。
    2. 客戶端從權威狀態重新模擬到其預測狀態,重新應用任何本地輸入。

實作

網路擁有權與預測

在伺服器權威模型中,您可以保持核心遊戲對象由伺服器擁有,而不會產生通常與伺服器擁有權相關聯的輸入延遲成本。像汽車、玩家角色或其他與遊戲玩法相關的關鍵對象可以保持伺服器擁有,即使在與其他玩家互動時也是如此。

默認情況下,Roblox 將自動對接近本地玩家的Character進行預測屬性,但如果您希望有更細粒度的控制,可以使用RunService:SetPredictionMode()明確強制實例的預測開啟或關閉。

模擬同步

在伺服器權威模型中,客戶端和伺服器必須運行核心模擬,並且客戶端的模擬需要能夠在發生錯誤預測回滾並重新模擬。為了啟用此功能,請將您的核心邏輯寫在通過RunService:BindToSimulation()綁定的函數中,這些函數在客戶端和伺服器上都會初始化。

伺服器權威設置

在重新模擬期間,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 自動同步所有具有模擬訪問的預測實例上的屬性。對於自定義數據,屬性是同步標記為預測的實例的主要方式;在這些實例上,伺服器的真相來源與客戶端的預測之間屬性值的不匹配將觸發完整的回滾和重新模擬

屬性限制

為了能夠複製,屬性必須滿足以下所有條件:

  • 它是其Instance上的前64個屬性之一。
  • 它的名稱最多包含50個字符。
  • 如果是字符串類型的屬性,其值最多包含50個字符。

模擬訪問

許多引擎 API 參考中的屬性和方法包含模擬訪問標籤,例如BasePart.CFrame。帶有此標籤的屬性將由伺服器權威系統進行預測。此外,僅帶有此標籤的屬性和方法可以在通過RunService:BindToSimulation()綁定的函數內訪問。

輸入行為

在伺服器權威遊戲中,客戶端影響遊戲狀態的主要方式是通過輸入行為系統。這些輸入被發送到伺服器,並在客戶端的重新模擬過程中重播。因此,應該對所有影響核心模擬的輸入使用InputActions,並且在處理之前應進行有效性檢查。

請注意,InputContexts必須是Player的後裔,以便引擎知道誰擁有InputContext。一種方法是將InputContexts添加到ReplicatedStorage下的資料夾中,並使用位於ServerScriptService下的Script按玩家克隆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.RenderSteppedRunService: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()
-- 透過 InputAction 將客戶端相機的前向向量發送到伺服器
local cameraForwardInputAction = Players.LocalPlayer.PlayContext.CameraForward
local cameraForwardVector = Workspace.CurrentCamera.CFrame.LookVector
cameraForwardInputAction:Fire(cameraForwardVector)
end)

遠程事件

遠程事件仍然可以在伺服器權威模型內部使用,以促進客戶端和伺服器之間的離散通信。例如,伺服器可以使用遠程事件來廣播有關玩家得分或撿到物體的數據,客戶端可以使用遠程事件作為發送輸入到伺服器的替代 API,例如按鈕按下或在3D世界中點擊物體。

動畫、聲音和效果

客戶端效果如動畫和聲音必須在知道客戶端模擬僅是權威伺服器狀態的預測的情況下編寫。BindToSimulation()限制了可以在綁定的函數內調用的屬性和方法,以幫助指導您僅對已同步的模擬狀態進行寫入。顯示此模擬的結果、觸發效果和聲音等應在連接到RenderStepped的單獨函數中完成,該函數讀取模擬的結果並觸發所需的效果。

有關渲染預測模擬的進一步指導在進階技術指南中涵蓋。

範例專案

除了這份文檔,以下模板可以幫助您入門:

賽車
足球
激光標籤
©2026 Roblox Corporation、Roblox、Roblox 標誌及 Powering Imagination 是我們在美國及其他國家地區的部分註冊與未註冊商標。