實例傳輸

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

經驗內的 實例傳輸 允許 Roblox 引擎動態載入和卸下世界各地的 3D 內容和相關實例。這可以以多種方式提升整體玩家體驗,例如:

  • 加入時間更快 — 玩家可以在世界的一個部分開始玩遊戲,而更多的世界在背景中載入。
  • 記憶體效率 — 體驗可以在記憶體更少的裝置上播放,因為內容會動態地進入和退出。更沉浸和詳細的世界可以在更廣泛的裝置上播放。
  • 改善效能 — 服務器可以花較少時間和帶寬同步世界與其中的玩家之間的變更,因此履約能提升。客戶花較少時間更新不與玩家目前相關的實例。
  • 細節程度 — 遠端模型和地形在不傳送到客戶端時仍然可見,保持體驗最佳化,而不是完全犧牲背景視覺。

啟用傳輸串流

實例傳輸通過 Studio 的 StreamingEnabled 屬性的 工作區 對象啟用。此屬性無法在腳指令碼中設置。新建在 Studio 創建的地點預設啟用傳輸。

The Properties window with the StreamingEnabled property enabled.

啟用後,建議您遵守以下做法:

  • 因為客戶通常不會擁有整個 Workspace 本地可用,請使用適當的工具/API 確保在 LocalScript 嘗試存取它們之前,實例存在。例如,使用 每個模型的串流控件 , 偵測實例串流 , 或使用 WaitForChild() 在可能不存在的對象上。
  • 盡量將 3D 內容放置在 Workspace 之外。像 ReplicatedStorageReplicatedFirst 這樣的容器內容不適合傳輸,可能會對加入時間和記憶使用產生負面影響。
  • 如果你移動玩家的角色,設置其 CFrame ,從服務器側 Script 進行操作,並使用 傳輸請求 來更快地載入角色新位置周圍的數據。
  • 手動設置玩家的 ReplicationFocus 只在獨特情況下,例如在不使用 Player.Character 的體驗中。在這些情況下,請確保焦點靠近玩家控制的對物件(s),以確保內容仍然在玩家的互動點周圍傳送。

技術行為

在流中

預設情況下,當玩家加入啟用實例傳輸的體驗時,在 Workspace 中的實例會複製到客戶端, 除了 以追蹤中內容:

然後,在遊玩期間,伺服器可能會將必要的實例傳送給客戶端,因為它們是需要的。

Diagram showing when various instances and their descendants in the Workspace stream in.
1 地形受到獨特對待,即當體驗載入時,實例會重複傳送給客戶,但地形區域僅在需要時流入

模型行為

模型設為非預設行為,例如 原子 傳輸在特定規則中,如 《模型傳輸控制》所述。但是,預設(非原子)模型會根據是否將 ModelStreamingBehavior 設置為 預設傳承 )或 改進 來不同地傳送。

The Properties window with the ModelStreamingBehavior property set to Default.

當 模型傳輸行為 設為 預設 / 舊版 時,容器和其非空間子孫,例如 會在玩家加入時複製到客戶端。然後,當符合資格時,模型的BasePart後裔進入。

Diagram showing default model stream in behavior.

輸出流

在遊玩期間,客戶端可能會流出(從玩家的 Workspace 區域中移除)和包含在其中的 BaseParts 區域,根據 StreamOutBehavior 設置的行為。過程從離玩家角色最遠的區域開始(或ReplicationFocus),隨需要靠近移動。在 StreamingMinRadius 範圍內的區域永遠不會流出。

當一個實例傳出時,它會被指派給 nil 以便任何現有的 Luau 狀態重新連接,如果實例重新傳入。因結果,移除信號,例如 ChildRemovedDescendantRemoving 在其 父親祖先 上發射,但實例本身不會以與 Instance:Destroy() 相同的方式被摧毀。

為了進一步預測流出,請考慮這些情況:

情況範例傳輸行為
零件是 創建 本地通過 Instance.new()LocalScript 中。在「捕捉旗標幟」遊戲中,您創建並附加藍色頭盔零件到所有藍隊玩家通過一個 LocalScript零件不會複製到伺服器,且不需要傳輸出 除非 你將它變成服務器上的零件的後裔,例如玩家角色模型內的零件。
零件是 複製 本地從 ReplicatedStorage 通過 Instance:Clone()LocalScript 中。巫師角色透過啟用 激活一個法術,在此法術上複製了包括多個 特殊效果 的對象到巫師位置的工作區。零件不會複製到伺服器上,且不需要傳輸出 除非 你將它變成伺服器上的零件的後裔。
一個零件是 重新整理ReplicatedStorage 到工作區通過 LocalScript一頂「巫師帽」被儲存在 ReplicatedStorage 中。當玩家選擇加入巫師隊團隊時,帽子會通過 LocalScript 移動到他們的角色模型。零件仍然可以傳送到服務器,因為它來自服務器並已複製到 ReplicatedStorage 。避免這種模式,因為它會導致客戶端和服務伺服器之間的同步失效,零件可能會流出;相反, 複製 零件。

模型行為

如果您將 模型傳輸行為 設置為 改進 ,引擎可能在適當時寫出 預設 ( 非原子 ) 模型,可能會釋放客戶端的記憶,並減少需要更新的實例。

The Properties window with the ModelStreamingBehavior property set to Improved.

在 改進 模型傳輸行為下,從 預設 ( 非原子 ) 模型中傳輸出是基於模型是否為 空間 (包含 子孫) 或 非空間 (沒有子孫)。

  • 空間模型只有在最後一個剩餘的 BasePart 子模型流出時才完全流出,因為模型的一些空間部分可能靠近玩家/複製焦點,而另一些則很遠。
  • 非空間模型只在祖先輸出時才會輸出,相當於舊版本輸出行為。

組裝和機制

當少於一部分的 裝配 可以在線傳輸時,所有裝配的零件也會在線傳輸。然而,裝配將不會在所有零件都可以傳輸出來之前傳輸出。在傳輸時,所有從 ConstraintsAttachments 下降的 BaseParts 和原子或永久 Models 也會傳串流,幫助確保在客戶端上保持一致的物理更新。

請注意,裝配具有 錨定部件 的裝配與只有未錨定部件的裝配的對待方式略有不同:

裝配組成傳輸行為
僅限未錨定的零件整個裝配以原子單位的形式傳送。
錨定 根部零件只有必要將傳送的零件鏈接到根零件的零件、附件和限制,才會一起傳送。

時間延遲

當零件在伺服器上創建和複製到客戶端之間可能會發生稍微延遲的 ~10 毫秒。在以下各種情況下,您可能需要使用 WaitForChild() 和其他技巧,而不是假設事件和屬性更新總是在部分傳輸與同時發生。

情況範例傳輸行為
A LocalScript 會向伺服器發出 RemoteFunction 呼叫,以創建零件。一名玩家會本地啟用 Tool 生成服務器上的零件,所有玩家都可以看到和互動。當遠端功能返回到客戶端時,零件可能尚未存在,即使零件靠近客戶端焦點和在傳輸區域內。
一個部分被添加到服務器上的角色模型通過 ScriptRemoteEvent 被發射到客戶端。當玩家加入警察團隊時,儲存在 ServerStorage 中的「警察徽章」部分會被複製並附加到玩家的角色模型上。A RemoteEvent 被該玩家的客戶發射和接收,以更新本地 UI 元素。雖然客戶接收到事件訊號,但並不保證零件已經傳送到該客戶端。
零件與伺服器上的隱形區域碰撞,並觸發在客戶端上的 RemoteEvent一名玩家將足球踢入球門,觸發「進球」事件。接近目標的其他玩家可能會在球傳送到他們之前看到「進球」事件。

傳輸屬性

下列屬性控制如何使實例傳輸適用於您的體驗。這些屬性都是 非可寫入 的,必須在 Studio 的 工作區 對象上設置。

The Properties window with the ModelStreamingBehavior, StreamingIntegrityMode, StreamingMidRadius, StreamingTargetRadius, and StreamOutBehavior property highlighted.

模型傳輸行為

控制是否在玩家加入時複製預設非原子)模型,或只在必要時傳送。如果此屬性設為 改進 ,在 中的模型只會在需要時傳送給客戶,可能會加快加入時間。請參閱技術行為以獲得更多細節。

傳輸完整性模式

如果玩家移動到世界上一個尚未傳送給他們的區域,您的體驗可能會以預期之外的方式運作。 傳輸完整性 功能提供一種方法來避免這些可能問題的情況。請參閱 Enum.StreamingIntegrityMode 文件以獲得更多詳情。

傳輸最小範圍

傳輸最小範圍 屬性指示玩家角色周圍的範圍 (或 ),在哪些情況下傳輸以最高優先級傳輸。當增加預設值時,應該小心,因為這會需要更多記憶和更多伺服器帶寬,而忽略其他組件。

傳輸目標範圍

傳輸目標範圍 屬性控制在傳輸到的案件中最遠離玩家角色 (或 ) 的最大距離。請注意,引擎可以保留先前載入的實例超出目標範圍,且記憶允許。

較小的 傳輸目標範圍 減少服務器負載,因為服務器不會在設置值之外的額外實例進行傳輸。然而,目標範圍也是玩家能夠看到您體驗全部細節的最大距離,因此您應該選擇一個值,可以創建這些之間的良好平衡。

傳輸出行為

StreamOutBehavior 屬性設置 傳輸出 行為,根據以下值之一:

設置傳輸行為
預設 預設行為,目前與 低記憶量 相同。
低記憶體 客戶只在低內存情況下傳輸零件,並可能在只有最小範圍存在時移除 3D 內容。
機會主義者 超出 傳輸目標範圍 的區域在客戶端上可以移除,即使沒有記憶壓力。在此模式下,客戶端永遠不會移除超過目標範圍的實例,除非在低記憶情況下。

每個模型的傳輸控制

全球上,模型傳輸行為屬性讓你控制模型在加入時如何傳輸。此外,為了避免以每個模型為基礎的串流問題和減少使用 WaitForChild() 的使用,您可以自定義如何 Models 和其子孫通過其 ModelStreamingMode 屬性進行串流。

The Properties window with the ModelStreamingMode property set to Default. The property is also highlighted.

預設/非原子

Model 設為 預設非原子 時,傳輸行為會根據 ModelStreamingBehavior 是否設為 預設 ( 舊版本 ) 或 改進 來變化。

模型傳輸行為技術行為
預設 ( 傳承 )當玩家加入時,模型會被複製。這可能會導致載入時發送更多實例、儲存在記憶中的更多實例,以及想要存取模型後裔的腳本的額外複雜度。例如,獨立的 LocalScript 需要在模型內的子 WaitForChild() 使用 BasePart
改善 模型只在需要時傳送,可能會加快加入時間。

查看 技術行為 以獲得更多細節。

原子

如果 Model 被更改為 原子 ,當子孫 BasePart 有資格時,所有子孫都會一起傳送。因結果,需要存取模型中的實例的單獨 LocalScript 將需要使用 WaitForChild() 在模型本身上,但不是在子孫 MeshPartPart 上,因為它們與模型一起傳送。

原子模型只會在所有下級零件都可以傳送時才會傳送出去,此時整個模型一起傳送出去。如果只有某些原子模型零件通常會被傳送出去,整個模型和其子模型都會留在客戶端上。

A diagram showing Atomic model streaming along with children.
本地脚本

local Workspace = game:GetService("Workspace")
-- 原子模型在載入時不存在;使用 WaitForChild()
local model = Workspace:WaitForChild("Model")
-- 下一代零件會與模型一起流入並立即可用
local meshPart = model.MeshPart
local part = model.Part

持久

永久 模型不受通常的串流輸入或輸出。它們很快就會被發送為完整的原子單位,在玩家加入和 Workspace.PersistentLoaded 事件發生之前。永久模型和其子模型永遠不會被傳送出去,但要安全地在單獨的 LocalScript 中處理傳輸,您應該在父模型上使用 WaitForChild() 或等待 PersistentLoaded 事件發觸發。

A diagram showing Persistent model streaming along with children.
本地脚本

local Workspace = game:GetService("Workspace")
-- 永久模型在載入時不存在;使用 WaitForChild()
local model = Workspace:WaitForChild("Model")
-- 下一代零件會與模型一起流入並立即可用
local meshPart = model.MeshPart
local part = model.Part

持久的每個玩家

模型設為 PersistentPerPlayer永久 對使用 Model:AddPersistentPlayer() 添加的玩家行為相同。對於其他玩家,行為與 原子 相同。您可以透過 Model:RemovePersistentPlayer() 將模型從玩家持久性中恢復。

請求區域傳輸

如果您將玩家角色的 CFrame 設置為未載入的區域,則會發生直播暫停,如果啟用。如果您知道角色將移動到特定區域,您可以呼叫 Player:RequestStreamAroundAsync() 要求服務器將該位置附近的區域傳送給客戶端。

以下的腳本顯示如何發射客戶端到服務器的 遠端事件 來傳送玩家到一個空間,在移動角色到新的 CFrame 之前,在傳輸要求中產生。

腳本 - 傳送玩家角色

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local teleportEvent = ReplicatedStorage:WaitForChild("TeleportEvent")
local function teleportPlayer(player, teleportTarget)
-- 請求在目標位置附近進行傳輸串流
player:RequestStreamAroundAsync(teleportTarget)
-- 傳送角色
local character = player.Character
if character and character.Parent then
local currentPivot = character:GetPivot()
character:PivotTo(currentPivot * CFrame.new(teleportTarget))
end
end
-- 當客戶端發射遠端事件時,呼叫傳送功能
teleportEvent.OnServerEvent:Connect(teleportPlayer)
本地腳本 - 發射遠端事件

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local teleportEvent = ReplicatedStorage:WaitForChild("TeleportEvent")
local teleportTarget = Vector3.new(50, 2, 120)
-- 發射遠端事件
teleportEvent:FireServer(teleportTarget)

偵測實例傳輸

在某些情況下,需要偵測當對象傳入或傳出時,並對該事件做出反應。一個有用的流式偵測模式如下:

  1. 使用實個體、實例的 標籤 部分或 Studio 的 標籤編輯器 ,為所有受影響的對象分配一個邏輯的 CollectionService

  2. 從單一 LocalScript 偵測標籤對象通過 GetInstanceAddedSignal()GetInstanceRemovedSignal() 傳送進入或退出,然後依照情況處理對象。例如,下面的代碼將標籤 Light 對象添加到"閃爍"循環中,當它們傳入時移除它們,當它們傳出時移除它們。

    本地腳本 - 收集服務傳輸偵測

    local CollectionService = game:GetService("CollectionService")
    local tagName = "FlickerLightSource"
    local random = Random.new()
    local flickerSources = {}
    -- 偵測目前和新標記的零件在內或外流式傳輸
    for _, light in CollectionService:GetTagged(tagName) do
    flickerSources[light] = true
    end
    CollectionService:GetInstanceAddedSignal(tagName):Connect(function(light)
    flickerSources[light] = true
    end)
    CollectionService:GetInstanceRemovedSignal(tagName):Connect(function(light)
    flickerSources[light] = nil
    end)
    -- 閃爍迴圈
    while true do
    for light in flickerSources do
    light.Brightness = 8 + random:NextNumber(-0.4, 0.4)
    end
    task.wait(0.05)
    end

自訂暫停螢幕

Player.GameplayPaused 屬性指示玩家目前的暫停狀態。此屬性可以使用 GetPropertyChangedSignal() 連線顯示或隱藏自訂 GUI。

本地脚本

local Players = game:GetService("Players")
local GuiService = game:GetService("GuiService")
local player = Players.LocalPlayer
-- 停用預設暫停模式
GuiService:SetGameplayPausedNotificationEnabled(false)
local function onPauseStateChanged()
if player.GameplayPaused then
-- 顯示自訂GUI
else
-- 隱藏自訂GUI
end
end
player:GetPropertyChangedSignal("GameplayPaused"):Connect(onPauseStateChanged)

模型細節程度

啟用傳輸時,當前傳輸區域外的 Models 將無法預設顯示。然而,您可以通過每個模型的 LevelOfDetail 屬性指示引擎渲染更低解析度的「捣乱者」網格給不存在於客戶端的模型。

LevelOfDetail property indicated for Model instance
A globe model displays in its actual level of detail.

實際模型
>

The same globe model displays as a low resolution imposter mesh with rough edges that obscure the globe's details.

低解析度「捣乱者」網格
>

模型設定傳輸行為
傳輸網格 啟用模型在客戶端不存在時顯示捣乱者網格的異步生成。
已停用 / 自動 當模型處於播放範圍之外時,模型將消失。

當使用捣乱者網格時,請注意以下事項:

  • 捣乱者網格設計為在 1024 單位遠離相機 或更遠處可見。如果您將 傳輸目標範圍 減少到像 256 這樣的更小值,擾亂者網格可能不適合替換的模型。
  • 如果模型 其子模型都設為 傳輸網格 ,只有最高級祖先模型被渲染為捣乱者網格,包括祖先和子模型下的所有幾何圖形。為了提高履約,建議您使用 停用 來創建子模型。
  • 不支持紋理;擾亂者網格被渲染為光滑網格。
  • 雖然 Model 尚未完全傳輸,但捣乱者網格會被渲染,而不是模型的個別部分。一旦所有個別零件都傳送進來,它們將渲染並忽略捣乱者網格。
  • 捣乱者網格沒有物理意義,並且在 射線投射碰撞偵測 和物理模擬方面作為不存在。
  • 在 Studio 編輯模型,例如添加/刪除/重新定位子零件或重設顏色,會自動更新代表網格。