為了支持複雜的物理機制,同時也為玩家提供平滑且響應的體驗,Roblox 物理 引擎使用一個分佈式物理系統,在此中計算會被分配到服務器和所有連接的客戶端之間。在這個系統中,引擎會將物理模擬的 網絡所有權 分配給客戶端或伺服器,將計算物理的工作分配給客戶端或伺服器。
客戶體驗到 更靈活 的物理互動,與他們擁有的零件,因為與伺服器通訊沒有延遲。網絡擁有權也會提高服務器性能,因為物理計算可以分配給個別客戶,讓服務器優先執行其他任務。
基本零件所有權
預設情況下,伺服器保留任何 BasePart 的所有權。此外,伺服器 總是 擁有錨定的 BaseParts ,您無法手動變更其所有權。
基於客戶的硬件能力和玩家對未錨定的 的接近度,引擎自動將那部分的所有權分配給客戶。因此,接近玩家角色的零件更可能成為玩家所有。
裝配擁有權
如果物理基礎機制沒有錨定的零件,設置所有權在該機制內的裝配中設置同樣的所有權 每個裝配 在機制內。
如果您錨定一個孤立的組件,該組件不是 一部分 的更廣泛機制的一部分,其所有權將歸服務伺服器所有,因為服務器總是擁有錨定的BaseParts。取消同一裝配的錨定後,其前一個擁有狀態將丟失,並且會恢復到引擎自動處理的狀態。
如果您將一個裝配錨定在更廣泛的裝配機制中,其所有權將歸服務伺服器所有,但其他裝配的所有權仍然不變。取消同一裝配的錨定會恢復其先前設定的擁有權。
設定所有權
在涉及複雜物理互動的體驗或在需要直接分配控制的情況下,您可以通過服務器端呼叫設置所有權到 BasePart:SetNetworkOwner() 。
考慮一輛車有 VehicleSeat 對駕駛者和 Seat 對乘客的物件,兩者都包含在車輛裝配中。如果玩家角色坐在 Seat (乘客),然後另一名玩家跳入 VehicleSeat (駕駛),那麼 乘客 獲得了整個車輛的物理所有權,因為他們先進入了。駕駛員必須等待幾個網絡週期才能讓輸入被認識,車輛感覺較少反應。
以下 Script 修正了這個問題,手動為驅動程式分配網路所有權。在它中,VehicleSeat 將其 Occupant 設為坐在它上的 Humanoid ,因此腳本會聆聽座位的Changed事件來捕捉玩家坐在座位時。當駕駛離開座椅時,車輛的網絡所有權將回復到自動狀態,使用 BasePart:SetNetworkOwnershipAuto() 。
local Players = game:GetService("Players")
local vehicleSeat = script.Parent
vehicleSeat.Changed:Connect(function(prop)
if prop == "Occupant" then
local humanoid = vehicleSeat.Occupant
if humanoid then
-- 從角色中獲得玩家
local player = Players:GetPlayerFromCharacter(humanoid.Parent)
if player then
vehicleSeat:SetNetworkOwner(player)
end
else
-- 當座位未佔用時重設所有權
vehicleSeat:SetNetworkOwnershipAuto()
end
end
end)
視覺化擁有權
為了幫助網絡擁有權檢查,Studio 可在遊戲測試時渲染對象周圍的彩色線圈。
外部色 | 說明 | |
---|---|---|
(綠色) | 您的客戶擁有零件並模擬它。 | |
(紅色) | 零件位於你的客戶模擬它的"緩衝區"內,但仍然屬於另一個東西。您的客戶可能會在此後獲得所有權,或可能會拒絕。 | |
(白色/灰色) | 服務器或其他客戶端通過自動網絡擁有或從明確指定的part:SetNetworkOwner()中擁有零件。 |
要啟用網絡所有權視覺化:
點擊3D視角右上角的 視覺化選項 按鈕。
在滾動選單中,切換到 網絡所有者 。
安全擔憂
當客戶擁有 BasePart 時,Roblox 無法驗證物理計算時。客戶可以利用這一點,向服務伺服器發送惡意數據,例如傳送 BasePart ,使其穿過牆壁或飛行。
此外, BasePart.Touched 事件與網絡所有權相關,意味著客戶可以在擁有的Touched 網絡上發射BasePart事件,即使服務器沒有看到它觸碰任何東西,也可以將它傳送到服務伺服器。例如,客戶端可以通過發射事件通過腳本注入對地圖上另一個玩家造成劍傷,因此很重要檢查客戶端發射的這類事件的有效性。
請參閱安全戰術和欺詐防禦策略,了解Roblox體驗的詳細安全戰術和欺詐防禦策略。