在体验中 实例串流 允许 Roblox 引擎在世界区域内动态加载和卸下 3D 内容和相关实例。这可以在多个方面提高玩家体验,例如:
- 更快的加入时间 — 玩家可以在世界的某个部分开始游戏,而世界的更多部分在后台加载。
- 内存效率 — 体验可以在更低内存设备上播放,因为内容动态地播放出入。更身临其境、更精彩的世界可以在更多设备上玩。
- 改进性能 — 更好的框架率和性能,因为服务器可以花更少的时间和带宽同步更改在世界上玩家和它的玩家之间。客户端花更少的时间更新不相关的实例。
- 细节层次 — 远程模型和地形仍然可以在不流向客户端时仍然可见,保持体验优化,并且不会完全牺牲背景视图。
启用流媒体
通过 Studio 中的 StreamingEnabled 属性,实现对实例的流媒。 此属性不能在脚本中设置。 流媒默认为 Studio 中创建的新地方。
启用后,您建议遵守以下实践:
- 因为客户端通常不会有整个Workspace可用本地,请使用适当的工具/API确保在LocalScript中尝试访问它们之前存在实例。例如,使用per-model streaming controls、2>检测实例 streaming2>或使用5>Class.Instance:WaitForChild()|WaitForChild
- 手动将玩家的 ReplicationFocus 设置为在不使用 Player.Character 的体验中独特的情况,例如在不使用 Class.Player.Character 的体验中。在这些情况下,请确保焦点靠近玩家控制的对象(s)以确保内容在玩家的互动点流动。
技术行为
在
默认情况下,当玩家加入带有工作间例流媒体启用的体验时,Workspace 中的实例会复制到客户端,除了以关注中/正在关注内容:
- 上述实例的后代
- 不复制实例
然后,在游戏过程中,服务器可能会将必要的实例流向客户,以便按需。
模型行为
模型设置为非默认行为,例如 Atomic 流在特殊规则下特殊规则中,但默认 (非原子) 模型根据是否设置 0> 模型流控制0> 为 3> 默认3> (6> 继承6> ) 或 9> 改进9> 。
当 模型流行行为 设置为 默认值 / 继承值 时,1> Class.Model 容器和其他非空间后代,例如4> Class.Script|Scripts 4>,在玩家加入时复制到客户端。然后,当有资格时,模型的
正在流出
在游戏中,客户端可能会流出 (从玩家的 Workspace 区域和其中包含的 BaseParts 基于StreamOutBehaviorStreamOutBehavior 的行为)。 过程首先开始于区域最远离玩家角色 (
当实例串流出时,它是父级的 nil ,因此任何现有 Luau 状态如果实例串回来,都会重新连接。因结果,除去信号如 ChildRemoved 或 <
要进一步预测流量,请检查这些场景:
场景 | 例子 | 流媒体行为 |
---|---|---|
有一个部分是 创建 本地通过 Instance.new() 在 LocalScript 中。 | 在“捕捉旗帜”游戏中,您创建并附加蓝色头盔部件到蓝队的所有玩家通过一个 LocalScript 。 | 零件不复制到服务器,且不适用于流媒体,除非您使其成为服务器上存在的零件的后代,例如玩家角色模型中的零件。 |
有一个部分是 克隆 本地从 ReplicatedStorage 通过 Instance:Clone() 在 1> Class.LocalScript1> 中。 | 一个巫师角色使用激活一个 Tool ,该 Class.ReplicatedStorage 中包含多个 ReplicatedStorage 的对象,并且在巫师角色的位置在 2>Class.ReplicatedStorage2> 中。 | 零件不复制到服务器,且不适用于流行出 除非 你使它成为服务器上存在的零件的后代。 |
零件是 从 Class.ReplicatedStorage 到工作区通过 Class.LocalScript 来重新父级。 | 一个“巫师帽”存储在 ReplicatedStorage 。当玩家选择加入巫师团队时,帽子将通过一个 LocalScript 移动到他们的角色模型。 | 零件从服务器直接传送到 ReplicatedStorage ,因此仍然适合直接播放。避免此模式,因为它会导致客户端和服务器之间的同步失败,并且零件可能会直播。 相反,请 克隆 零件。 |
模型行为
如果您将ModelStreamingBehavior设置为改进,引擎可能会在适合流行时流出默认模型(2>非原子2>),因此可能会在客户端上节省内存并减少需要属性更新的实例。
在 改进 模型流媒体行为时,流媒体从 默认 (含 非原子 模型) 流媒体是基于是否是 2>空间2> (包含 5> Class.BasePart5> 后代) 或 8>非空间8> (包含无 1> Class.BasePart 1>
- 空间模型只会在其最后剩余的 BasePart 后流出,因为一些模型的空间部分可能靠近玩家/复制焦点,而一些部分可能靠近远处。
- 非空间模型只会在上一个父辈流出时播放,这与传统的播放模式不同。
组合和机制
当至少一个部分的Assembly可以被视为可以串流的时候,所有的Assembly部分也会串流。但是,在 streaming 的时候,所有的Class.Instance|Instance和
注意, 锚定 零件的组合会与只有未锚定零件的组合处理有些不同:
装配工序 | 流媒体行为 |
---|---|
仅限非固定零件 | 整个装配发送为原子单位。 |
树莓根 部分 | 仅有需要连接流动部件到根部的部件、附件和限制部件才会一起流动。 |
时间延迟
在服务器上创建零件和在客户端复制时可能会有~10毫秒的延迟。在以下各个场景中,您可能需要使用 WaitForChild() 和其他技术,而不是假设事件和属性更新总是在零件流媒体上发生。
场景 | 例子 | 流媒体行为 |
---|---|---|
一个 LocalScript 使用 RemoteFunction 调用服务器创建零件。 | 一位玩家在本地激活 Tool 以生成一个部分在服务器上所有玩家都可以看到和交互的部分。 | 当远程函数返回客户端时,零件可能还不存在,即使零件位于客户端焦点附近并且在直播区域内。 |
有零件添加到服务器上的角色模型通过 Script 和 RemoteEvent 来一个角色。 | 当玩家加入警察团队时,一个“警察徽章”部分存储在 ServerStorage 中,并且附在玩家的角色模型上。一个 RemoteEvent 发射并受到该玩家客户端以更新本地界面元素。 | 尽管客户端接收到事件信号,但是没有保证零件已经流向那个客户端。 |
服务器上的某个部分与服务器上的隐藏区域碰撞,并触发客户端上的RemoteEvent。 | 玩家踢球进球,触发“进球得分”事件。 | 靠近目标的其他玩家可能会在球被流到他们之前看到“进球得分”事件。 |
流媒体属性
以下属性控制实例流媒体对您的体验的应用。 所有这些属性都是 非脚本 ,必须在 Studio 中的 工作区 对象上设置。
模型流式行为
控制玩家加入时是否复制默认 (非原子 ) 模型,或在需要时发送。如果此属性设置为 改进 ,1> Class.工作间orkspace1> 的模型仅在需要时发送给客户,从而可能加快加入时间。请参阅4>技术行为4>了解更多信息。
实时集成模式
如果玩家移动到世界的某个区域,而未被流媒到那里,那么您的体验可能会以意外的方式行为。 播放整洁度 功能提供了一个方法来避免这些可能会带来问题的情况。请参阅 Enum.StreamingIntegrityMode 文档获取更多信息。
流量最小直径
StreamingMinradius 属性表示在玩家角色 (或 ReplicationFocus ) 周围的流量最高优先级的实例。增加默认值时,需要更多内存和更多服务器带宽,这会在其他组件的代价上提高。
流媒体目标距离
StreamingTargetRadius 属性控制着从播放器角色 (或 Class.Player.ReplicationFocus|ReplicationFocus) 到播放器流量的最大距离。注意:引擎允许您在目标范围之外保留先前加载的实例,并且允许您的内存。
较小的 StreamingTargetRadius 减少服务器工作量,因为服务器不会在额外的实例之上流量。 但是,目标radius是最大距离玩家能够看到您的体验的完整细节,因此您应该选择一个值,这将创建一个良好的平衡。
流式行为
StreamOutBehavior 属性设置了 串流出 行为,根据以下值之一:
设置 | 流媒体行为 |
---|---|
默认值为 | 默认行为,目前与 LowMemory 相同。 |
低内存 | 客户端只会在内存情况不佳时流出零件,并且在最小范围内移除 3D 内容。 |
机会主义者 | 超出 StreamingTargetRadius 的区域可以在客户端上移除,即使没有内存压力。在此模式下,客户端永远不会移除离目标径径更近的实例,除了在低内存情况下。 |
根据模型的流媒体控件
在全球范围内,ModelStreamingBehavior 属性允许您控制模型如何在加入时播放。此外,为了避免与串流在模型基础上流行的问题并最小限度地使用 WaitForChild(),您可以自定义 Class.Model|ModelStreamingMode|ModelStreaming
默认/非原子
当 Model 设置为 默认值 或 非原子值 时,流媒体行为因为是否设置 2> ModelStreamingBehavior2> 为 5> 默认值 5> ( 8> 继承值8> 或 Model1> ) 而变得不同。
模型流媒体行为 | 技术行为 |
---|---|
默认值 ( 继承值 ) | 当玩家加入时,模型会复制。这可能会导致加载时发送更多实例、存储更多实例在内存中,以及对要访问模型子脚本的脚本添加额外的复杂性。例如,一个单独的 LocalScript 将需要使用 WaitForChild() 在模型的子脚本。 |
改进了 | 模型仅在需要时发送,可能会导致加入时间的潜在加速。 |
请参阅技术行为了解更多信息。
原子
如果 Model 被更改为 Atomic ,其所有后代都会一起流入模型,从而使得需要在模型上使用 Class.Instance:WaitForChild
原子模型只有在所有的子部分都可用于流式分发时,才会流式分发。 在此时,整个模型和其子部分都会保持在客户端上。 如果只有某些部分的原子模型可能会流式分发,整个模型和子部分将会保持在客户端上。
本地脚本
-- 原子模型在加载时不存在;请使用 WaitForChild()local model = workspace:WaitForChild("Model")-- 下游零件流入模型,并立即可以访问local meshPart = model.MeshPartlocal part = model.Part
持久
持久模型不受正常流媒体在或出。它们作为完整原子单元很快就会发送给玩家,并在 Class.Workspace.PersistentLoaded 事件发生之前。持久模型和其子模型永远不
本地脚本
-- 持久模型在加载时不存在;请使用 WaitForChild()local model = workspace:WaitForChild("Model")-- 下游零件流入模型,并立即可以访问local meshPart = model.MeshPartlocal part = model.Part
持久的玩家
将模型设置为 持久玩家 与持久 玩家 相同为止。 对于其他玩家,行为与 Model:AddPersistentPlayer() 中的玩家相同。 您可以通过 1> Class.Model:RemovePersistentPlayer()1> 来从玩家持久性过程中恢复。
请求区域直播
如果您将玩家角色的 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)
检测实例流媒
在某些情况下,它是必要的检测当一个对象通过或向外流量时,并且对该事件作出反应。一种有用的流量检测模式如下所示:
使用实例的属性的 标签 部分,或 Studio 的 标签编辑器,为所有受影响的对象分配一个逻辑 CollectionService 标签。
从单个 LocalScript ,检测标记对象是否通过 GetInstanceAddedSignal() 和 GetInstanceRemovedSignal() 来流入或流出。然后根据对象的情况添加标记
本地脚本 - 集合服务流媒体检测local CollectionService = game:GetService("CollectionService")local tagName = "FlickerLightSource"local random = Random.new()local flickerSources = {}-- 检测当前和新标记的零件是否在流入或流出for _, light in CollectionService:GetTagged(tagName) doflickerSources[light] = trueendCollectionService:GetInstanceAddedSignal(tagName):Connect(function(light)flickerSources[light] = trueend)CollectionService:GetInstanceRemovedSignal(tagName):Connect(function(light)flickerSources[light] = nilend)-- 闪烁循环while true dofor light in flickerSources dolight.Brightness = 8 + random:NextNumber(-0.4, 0.4)endtask.wait(0.05)end
自定义暂停屏幕
Class.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
-- 隐藏自定义图形用户界面
end
end
player:GetPropertyChangedSignal("GameplayPaused"):Connect(onPauseStateChanged)
模型细节层次
当启用直播时,Models 在当前直播区域外不会默认显示。但您可以通过将 LevelOfDetail 属性的每个模型的 Class.Model 指定为“低解析度”“imposter”网格,为不在客户端通过每个模型的 1> Class.Model.LevelOfDetail|LevelOfDetail1> 属性显示的模型提供
模型设置 | 流媒体行为 |
---|---|
网络Mesh | 激活捣乱模型网格的异步生成,以便在客户端不存在时显示。 |
已禁用 / 自动 | 当模型位于流媒体流量范围之外时,模型将消失。 |
使用捣乱者网格时,请注意以关注中/正在关注:
- 捣乱者网格是用于在 1024 从相机远处或更远地方看到 Camera 或更远地方。 如果您将StreamingTargetRadius减少为 256 或更小,捣乱者网格可能无法视觉上接受该替换的模型。
- 如果一个模型 和 其子模型是所有设置为 StreamingMesh 的,只有上级祖先模型才会渲染为伪装网格,将所有几何图形包含在祖先下级模型下。为了获得最佳性能,请使用 Disabled 对子模型。
- 不支持纹理;捣乱者网格将以光滑的网格渲染。
- 虽然 Model 不完全串流在,但是捣乱网格会在模型的各个部分而不是单个部分来渲染。 一旦所有的部分都串流在一起,它们会渲染,而捣乱网格会被忽略。
- 在 Studio 中编辑模型,例如添加/删除/重置子零件或重置颜色,会自动更新代表网格。