首页 / 大项目模块 / 传送 / 流送与 WP · 代码实现

流送与 WP · 代码实现

概念层(WP Cell、DataLayer 前缀、两盏灯的原理)在 横向专题 · 地图流送与 DataLayer 里已经讲透。 本页换一个视角:从八个代码文件出发,看一次场景加载或传送在流送这条线上到底排了哪些命令、 谁在驱动引擎、预加载为什么必须是三段式。

8 个文件 两盏灯 三段式预加载 假阳性 残留流送态

1. 全景图

下面这张图把「服务端就绪 → 命令组装 → 四步命令链 → 两盏灯流送 → 三段式预加载」串成一条线。 后面每一节都可以回到这张图上找到自己的位置。

流送全景图:服务端就绪经命令组装进入四步命令链,由两盏灯与临时流送源驱动,SceneLoadingController 负责三段式 WP 预加载

2. 八个文件的分工

文件职责关键符号
SceneLoadingController流送总控制器:服务端关卡就绪后的主加载,以及 WP DataLayer 的预加载与还原 / 取消OnServerLevelReady@98 · LoadSceneMain@111 · PreloadWpDataLayers@188 · FinishPreloadWpDataLayer@430 · RestorePreloadDataLayers@468 · CancelPreloadWpDataLayer@550
SceneLoadingCommandHelper流送 / 传送命令的组装工厂:把「加载什么场景、怎么流送、怎么传送」翻译成命令TeleportInfo@40 · GetSceneLoadingType@78 · SetLoadingContextBornTransform@147 · GetFallbackCameraDirPos@234 · BuildSceneLoadingCommand@384 · BuildSceneTeleportCommand@425
StreamingSourceInfo单个流送源的状态与位置:按帧更新位置、设置锁定状态,并判定流送是否完成EStreamingSourceState@11 · Tick@39 · UpdateStreamingSourcePosition@61 · SetStreamingLockStateAndPosition@70 · IsStreamingCompleted@200
TransientStreamingSource临时流送源:支持跟随目标或固定在指定位置两种模式,可批量创建 / 推进 / 销毁InitFollowMode@43 · InitFixedMode@68 · CreateWithFollowTarget@376 · CreateAtPosition@419 · TickAll@546 · DestroyAll@574
SceneWaitWpStreamingCmd命令链里的「等 WP 流送」节点:按是否需要地形流送决定等不等,持有所用的 timer 与 PromiseCancelStreamingWait@31 · WaitWpStreaming@46 · OnExecute@99
SceneLoadingWpMapCmdWP 地图加载命令:把主地图、等流送、加载期移动、等传送完成四步串成一条链OnAddInitCommand@27 · SceneLoadingMainMapCmd@43 · SceneWaitWpStreamingCmd@73 · SceneLoadingMoveCmd@76 · SceneLoadingWaitTeleportCmdFinishedCmd@100
SceneLoadingTeleportCmd流送场景下的传送命令:判断是否在流送中、是否需要 Loading UI,并装配上下文初始化与等待流送isInSceneLoading@19 · needLoadingUi@23 · SceneLoadingWpMapCtxInitCmd@32 · SceneWaitWpStreamingCmd@59
SceneLoadingWaitTeleportCmdFinishedCmd等待传送命令彻底结束,带 180 秒超时WaitTeleportTimeoutMs=180000@14 · HandleOnTeleportCmdFinished@64 · HandleWaitTimeout@70 · OnExecute@74

3. 主链路:一次加载排了哪些命令

1
服务端关卡就绪
SceneLoadingController.OnServerLevelReady@98 是客户端加载与「服务端已就绪」对齐的关键信号,收到后进入 LoadSceneMain@111 主加载。
2
组装命令
SceneLoadingCommandHelper 用 TeleportInfo@40 与 GetSceneLoadingType@78 判断这是换图、换层还是无缝,再由 BuildSceneLoadingCommand@384 / BuildSceneTeleportCommand@425 拼出命令。加载期出生点由 SetLoadingContextBornTransform@147 决定,相机兜底朝向由 GetFallbackCameraDirPos@234 决定。
3
装配四步链
SceneLoadingWpMapCmd.OnAddInitCommand@27 依次挂上:主地图加载(@43)→ 等 WP 流送(@73)→ 加载期移动(@76)→ 等传送完成(@100,180 秒超时)。
4
等流送
SceneWaitWpStreamingCmd 先看 Context.NeedsTerrainStreaming:非 SwitchDimension 需要等;SwitchDimension 里无缝换落点也要等;只有普通原地无缝才跳过。要等就走 WaitWpStreaming@46,最终等 GameModeController.CheckTargetStreamingCompleted。
5
流送源驱动
引擎侧的流送由两盏灯和临时源驱动,判定依据是 StreamingSourceInfo.IsStreamingCompleted@200。
6
收尾
等传送完成后归还临时流送源、清 timer;预加载过的 DataLayer 该还原还原、该取消取消。

4. 两盏灯:流送源怎么跟着走

项目里维护两类常驻流送源,加上一类句柄式临时源。

流送源行为位置
灯① StreamingSourceInfo跟随玩家位置,每帧用 Tick@39 / UpdateStreamingSourcePosition@61 更新决定玩家脚下附近的 cell 什么时候被加载,是「平时」流送的主力
灯② TargetStreamingSourceInfo用 SetStreamingLockStateAndPosition@70 强制锁在指定位置(通常是传送目标落点)玩家还没到,先在目的地把地形流好,这是逐图流送的关键
临时源 TransientStreamingSource一次性使用:CreateWithFollowTarget@376 跟随某目标、CreateAtPosition@419 固定在某个位置,由 TickAll@546 批量推进用完必须 DestroyAll@574 回收,否则源源不断产生流送开销

流送源的状态用 EStreamingSourceState@11 表示,从 Unload 到 LoadAndHide(载入但隐藏,对应 Loaded), 再到 LoadAndVisible(载入且可见,对应 Activated)。

假阳性:Activated 不等于碰撞就绪 cell 已经进入 Activated,不代表碰撞体、NavMesh 就绪了。 IsStreamingCompleted@200 的判定要和这个认知对齐,否则会把「看起来流完了其实还没好」当成引擎 bug。 详见 横向专题 · 假阳性。

5. 三段式预加载:预加载 → 完成 → 还原 / 取消

WP DataLayer 的预加载是三段式,缺一不可。

1
预加载
PreloadWpDataLayers@188 批量、PreloadWpDataLayer@180 单个,把请求挂成 IWpPreloadRequest(字段含 Id / Position / DataLayers / TargetDataLayerState / Promise / PollTimer / TimeoutTimer / IsCompleted),轮询目标层是否到达目标状态,并用超时 timer 兜底。
2
完成
FinishPreloadWpDataLayer@430 在达标后结算 Promise、标记 IsCompleted 并通知调用方。
3a
还原
RestorePreloadDataLayers@468 把预加载过的层还原回原状态。
3b
取消
CancelPreloadWpDataLayer@550 取消进行中的预加载并清掉 timer。
取消与还原都要做 只预加载而不还原、不取消,DataLayer 会一直停留在流送态,表现为「上一层图的状态漏到这一层」。 所以「预加载 → 完成 → 还原 / 取消」这三段必须成对出现。

6. 排查要点速记