伺服器權限模型

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

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

優勢

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

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

有時,客戶端的預測會錯誤(預測錯誤),由於網路延遲,客戶端將不會知道自己已經犯錯幾幀。例如:

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

設定

伺服器權限模型需要某些其他引擎技術才能正確運行。請確認 Workspace 對象在 Explorer 中的以下屬性設置:

  1. Workspace.AuthorityMode 必須為 Server(設置此值會自動設置以下五個)。

概念

伺服器權限系統運行於幾個核心概念,如下所示。

客戶端預測

通過客戶端預測,客戶端在最後已知的伺服器狀態之上模擬幾幀,以立即預測玩家輸入的效果。這隱藏了輸入延遲,但預測可能後來證明是錯誤的(客戶端預測錯誤),因此需要修正。客戶端試圖在最後已知的權威伺服器狀態之前模擬足夠的幀,以確保其輸入能在預定的幀到達伺服器。客戶端會預測多少幀是根據客戶端和伺服器之間的延遲。

客戶端預測錯誤

當客戶端從伺服器接收到權威狀態時,它會將該狀態與其本地預測的歷史記錄進行比較。在客戶端預測和伺服器實際發生之間存在差異時,這就構成了一個預測錯誤。預測錯誤可能由幾個原因引起,包括網路延遲的變化、其他玩家的行為客戶端未能預見、遊戲過程中某些邏輯僅在伺服器上運行等。

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

回滾和重新模擬

當客戶端檢測到預測錯誤時,它必須重置為伺服器的權威狀態,然後重新模擬,以跳回到其預測的幀。根據網路延遲,客戶端會嘗試在最後已知的權威伺服器狀態之前模擬得足夠遠,以確保其輸入能在預定的幀到達伺服器。

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

總結來說,客戶端

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

實現

網路擁有權和預測

在伺服器權限模型中,你可以保持核心遊戲對象由伺服器擁有,而不會承擔通常與伺服器擁有權相關的輸入延遲成本。像汽車、玩家角色或其他關鍵遊戲對象,即使與其他玩家交互,也可以保持由伺服器擁有。

默認情況下,Roblox 將自動預測接近本地玩家 Character模擬訪問屬性,但如果你想要更精細的控制,可以通過 RunService:SetPredictionMode() 明確強制實例的預測開啟或關閉。

模擬同步

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

伺服器權限設定

在重新模擬期間,Roblox 將重新運行通過 RunService: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 下的文件夾中,並使用 ScriptServerScriptService 下克隆每個玩家的 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 輸入動作時觸發角色運行。

遙控事件

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

動畫、聲音和效果

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

有關渲染預測模擬的進一步指導,請參見進階技術指南。

範例專案

除了本文件外,以下模板可以幫助你入門:

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