首页 / 传送 / 统一安全落位设计

统一安全落位设计(延期重构)

先准备目标,再提交位移;有遮罩的普通地面传送,必须站稳且模型复位后才显露。统一的是安全落位能力,不是把坠落处罚、死亡复活、跨图和 Seq 演出揉成一个业务流程。

2026-09-23 决策更新延期重构/暂不实施完整设计保留实机待验收
2026-09-23 用户决策:当前仅延后普通黑屏撤罩

当前不做大重构。局部补丁仅调整普通黑屏消失条件:现有落位 → 站稳/逻辑 Idle/动画 Idle/Mesh 就绪观察 → 撤罩;不改网络接管、目标预加载、跨图、Seq3 或 V2。

新增等待只观察就绪条件,不再落位;这不等于全链已做到单次权威提交。上游提前移动、重复落位与统一提交仍留待以后重构,不能宣称已解决。

当前 Mesh 判据是在一次 Reset 后,观察多个不同 PoseTick 保持 ground、逻辑 Idle、动画 Idle 和静止的表现更新;不是严格的本次 OBR 最终求值回执,仍需实机验收。

原生 GroundFacts.SampleFrame / Revision 已确认可从 UE.GameMovementMiddlewareComponent.GetActorGroundFacts 读取;接地采样可读不等于 Mesh/OBR 复位已有严格完成回执。

以下第 1–13 节完整保留原设计供以后重构参考,其中“本次”“计划”“待确认”均指延期的完整方案,不是当前补丁范围或实施授权;未来重启仍须审阅和技术验证。

阅读顺序

先看 三种模式、统一时序、坠落重生、跨图边界;实现前核对 验证门槛和待确认规则。本页是新设计,不表示旧安全等待文档描述的代码已被替换。

1. 本次范围与结论

2. 三种同图模式:只允许 UI load 主动加载

模式 目标准备 遮挡与落位 移动模式
无缝 只检查现有目标碰撞/落点;不创建目标流送源,不启动加载命令 不主动黑屏、不打开 Loading;目标已可用才瞬移并请求模型复位 不主动调用 GameSetMovementMode,不以传送名义统一锁重力
范围内黑屏 与无缝一致:只查询已加载的目标 等黑屏真正遮住 → 单次落位 → 站稳、Idle、Mesh 就绪 → 撤罩 保持前轮要求:普通黑屏不设置/恢复 MovementMode
UI load 玩家留在原区域;独立目标源加载目标 Cell/DataLayer,并验证碰撞和可站立位置 Loading 已遮挡 → 目标准备好 → 单次落位 → 站稳与模型就绪 → 关闭 Loading 允许必要的临时移动保护,但不默认全程 Walking+零重力

“不加载”指不主动启动目标预加载,不关闭 World Partition 跟随玩家的正常流送。距离只能作为表现偏好,不能证明目标可站;现有 100m 阈值不再作为安全判断。

目标未就绪时的建议,需审阅确认

无缝/黑屏的即时预检若发现地形不具备落位条件,显式切换为 UI load,记录升格原因,再启动目标流送。这不算“黑屏模式偷偷加载”。若产品要求绝不升格,则保持不移动并走故障等待,不能强行传送。目标已加载但位置非法,不能靠重复加载假装修复,应由业务选择合法备用点或保持失败保护。

模式、业务、表现分开表达

现有 ETeleportType 是业务枚举,不替换为三种策略。BLACK/WHITE 是遮罩颜色,FADE_IN_OUT 是表现,均不直接代表 UI load。普通无演出入口先按既有意图选无缝/黑屏,再作就绪检查;已有明确 Loading 意图保留 UI load。配置到通知的完整映射需在最小验证中确认,不能猜测默认字段的含义。

3. 整体扫描发现的关键缺口

已读代码事实 影响 本次处理
CombatMessage 位移前发 LocalPlayerServerMoveApplied,BaseMoveSync 后续还会再发;传送接管后 Base 分支仍可直接移动 “目标加载完再移动”在上游就被打破,同一请求可能落位两次 区分收到目标与真正提交;在任何本地 Actor 写位置之前决定接管;Applied 只表示实际提交
SameScene 当前在流送成功后先 SafeMoveTeleport,再 WaitForGroundReady 没有提交前碰撞门,也没有实际角色 Idle 门 拆成准备、提交、收敛三个阶段
无缝/Fade 当前仍调用快照流送;SceneLoadingTeleportCmd 还含事件、场景信息和源交接 与新三模式语义不一致;旧命令不是纯等待工具 拆开纯目标准备与必要业务通知,不能整条旧命令照搬
CommandBail 会进入结果回调;坠落和 WithStreaming 的部分回调未检查 result 旧请求取消后仍可能继续传送、锁源、关新请求遮罩 结果状态+请求代次+资源 owner 三重检查
九点射线不检查完整胶囊空间、实际接地、姿态;窄平台可能永远不通过 射线全命中不是“已站稳” 保留必要诊断,安全契约改为角色尺寸相关的落点查询与实际接地证据
ResetOffsetRootBone 原生只置请求标志,动画 NativeUpdateAnimation 才消费 调用返回/固定 200ms 不是模型复位完成证明 动画实际更新与模型位置验证先做最小实测,禁止业务读取消费接口抢走请求
主流送源会跟随玩家;目标源被场景预加载和旧保活共同使用 玩家未移动时提前交接,主源可能又跟回旧区域 目标源保活至主源确认覆盖目标,旧 owner 不能释放新 owner 的源
跨图 After 先 LoadDone 握手,后处理/创建角色 把 LoadDone 移到“新角色 Idle 后”会产生等待环 协议握手保持原位,角色安全与显露另设阶段

以上是静态代码核查结论,不是原始 Mesh 故障的完整运行时因果证明。前轮二次 Reset+200ms 补丁尚无游戏复测,不能作为新架构已验证的依据。

4. 统一时序:准备 → 唯一提交 → 站稳 → 显露

1
接收请求 Accepted
确认本地角色和业务 owner;保存不可变目标、源位置、朝向、实体/世界/关卡/连接身份及 version、generation。先隔离本地上行,再发布“目标收到”。
2
准备目标 PreparingTarget
无缝/黑屏仅查询;UI load 获取目标源所有权并流送。只做目标查询,禁止任何会修改 Actor 的贴地函数。原地保护按角色当前姿态决定。
3
提交前复核 ReadyToCommit
目标碰撞、胶囊容纳、站立坡面/支撑成立;请求仍有效。黑屏/Loading 必须已真正遮挡。源与目标变化时重新查询,不能使用失效候选点。
4
唯一落位 Committed
在合适的 PrePhysics 阶段清旧速度和旧位移队列,提交位置/朝向,核对原生移动结果及实际 transform,再请求 OffsetRootBone 复位。仅成功提交才发布 Applied。
5
落位收敛 Settling
保持必要输入与上行隔离,但允许需要的物理和动画 Tick 更新。在新位置读取新鲜接地证据,验证目标姿态和模型对齐;UI load 同时完成主源接管。
6
完成 Completed
按各业务协议完成握手;释放自身保护,清旧上行样本并在目标位置开始新采样;有遮罩者满足安全和表现条件才关闭。终态回调至多一次。

“单次落位”是每个已接管请求只有一次权威传送提交,普通物理贴地修正不是第二次传送。无缝没有遮罩可等,必须先满足可立即显示的条件;若动画复位首帧仍会露出拖尾,就不能宣称无缝质量已达标,须先完成动画验证或按审阅后的规则升格。

共享能力的最小结构

保留 TeleportController 门面、SameSceneFlow 编排、Presentation 表现和 GroundProbe 查询。计划新增一个轻量 TeleportPlacementFlow(暂定名,待验证后确定)承接请求身份、提交与 Settling,供同图和坠落复用;跨图调用其查询/验证能力,不强行接管整条场景链。不另建一套通用任务框架或全局服务注册体系。

5. “站在地面且 Idle”如何判断

检查层 普通地面传送的要求 不能替代它的东西
提交前目标 可用碰撞、可走支撑面、角色胶囊不穿透、落点修正量在业务许可内 只有 WP Activated;远处一条射线命中
提交结果 原生位移成功且实际位置符合候选落点;请求/角色身份仍一致 SafeMoveTeleport 返回 void;FixBornLocation 返回候选成功
实际接地 提交后新鲜物理 GroundFacts 表明接地,胶囊脚底与支撑面合理 旧位置缓存;强设 MOVE_Walking
逻辑姿态 地面 Phase+NotMoving,速度在验证确定的容差内;无技能/演出继续驱动 单独 NotMoving:受击、技能、死亡阶段也可能映射到它
模型 复位请求经过实际动画更新,渲染相关 Mesh/根骨偏移回到角色合法基准附近,连续采样稳定 调用 Reset 就当完成;固定 200ms;仅 Mesh 组件 transform(根骨偏移可能仍在)

不硬编码“Mesh 和 Capsule 原点相同”:角色合法相对偏移、体型和动画根骨均不同。采样接口、帧数、容差通过 Demo 确定。现有 TS 没找到完整复位回执;若无法可靠观测,需要动画模块提供支持建议,在获得授权前不修改 Native 或生成 Typing。

普通黑屏不强设 MovementMode。落位后给原生物理正常刷新机会,由实际接地推动 Grounded/NotMoving。如果必须改模式才走得通,应报告验证失败并重新审阅,不能偷偷加回 Walking。

原位置安全不等于永远不需要保护

6. 网络、取消和流送源:必须同时补齐

6.1 本地位移接管与上行屏障

6.2 通知乱序的真实能力边界

WorldTeleportSelfSCNotify 只有表现/方向等字段,没有共同 requestId 或 serverMoveVersion。客户端 generation 可以阻止旧异步回调,但不能凭空证明表现通知属于哪个 ServerMove。设计以权威目标包建立事务,表现通知只在业务上下文唯一、关联条件成立时使用;不能拿“最近一份快照”无条件拼接。模糊关联时走保守安全表现,不承诺演出配对绝对正确。最小验证必须覆盖倒序和连续通知;若产品要求并发请求严格配对,需另提服务端协议建议,本次不改服务端。

6.3 取消、失败、交接是不同结果

6.4 目标流送源的所有权

UI load 获取目标源 owner → 设置目标位置/层并激活 → 等 Cell 和碰撞 → 提交玩家 → 主源跟随并确认覆盖目标 → 释放目标源。主源未接住时不按固定 30 秒认定交接成功。目标源是全局共享资源,场景预加载、跨图和传送保活也必须遵循同一 owner 规则;不同时新增第二套互不知情的锁。复制 StreamingSourceInfo 不等于复制锁状态,也不等于主源已覆盖目标。

7. 坠落重生:处罚入口不变,复用落位

触发/规则/请求 → 获得合法重生点 → 选择黑屏或 UI load → 共享安全落位 → 业务完成。

死亡复活仍由 PlayerDeath/RoleRevive 负责生命状态、溶解和 Montage。边界入口若本就转坠落,可随该适配获益;其提示和触发条件不改。

8. 跨图:共享安全门,不改握手含义

1
场景准备
保留旧场景离开、目标地图/层、资产、WP 加载流程。查询使用目标 World context,不依赖旧 Global.BaseCharacter。
2
After 握手与角色创建
跨图 LoadDone 保持在取得/处理实体回包的原有阶段。创建前登记目标事务保护,防激活开碰撞和 Tick 后、验证接入前的空窗。
3
创建完成后验证/无缝换落点提交
确认本地绑定和目标身份,不只看 EntityCreated。复用目标与实际落位检查;After 内 IsSeamlessRelocate 的直写位置也纳入唯一提交边界。
4
显露或者移交 Seq3
普通落地验证通过才显露;演出由 Binder 接管角色,共享层不抢写位置。EndClientLoading 仍能驱动 Seq3,不能在此前等待 Seq3 完成。
协议/事件 保持的责任
同图 LoadDone 关联 serverMoveVersion;普通同图路径安全条件满足后按原栅栏规则发送/重试
跨图 LoadDone 关联 world/level;场景准备后握手,之后可能才获得角色实体,不能后移到新角色 Idle
SceneLoadAnimDone 保持演出完成语义,不当作物理落位回执

Seq3/V2 是受控例外:演出可能需要降落,不强制在起播前普通站立 Idle。起播要求资产/绑定/首帧姿态和目标环境就绪;演出归还控制时再验证普通角色恢复。普通 Binder 与 V2 私有 Binder 各自保留,只统一请求身份和交接约束。恢复同步前先清速度/旧样本,避免即时采样带走演出残留。

9. 等待失败策略:不伪成功,也不擅自退登

沿用 既有“异常只记录、不自动退登”决策。安全未成立不得因计时到点而移动、撤罩或发同图成功;跨图握手不属于这类物理完成回执。每个异步阶段都必须可取消并有诊断截止点,截止后进入明确的故障保持状态或交还 owner,而不是静默挂住 Promise。

代价明确:若目标永远不可用且没有新请求或外部恢复,用户仍可能长时间被遮挡。这个产品取舍未因本方案自动改变。

10. 文件职责与建议改动边界

工作区:D:\zhaozibo_071\Source\Client\TypeScript。以下为本轮读取时的职责快照;全部是计划,不是已提交的代码改动。

传送目录文件(15 个) 处置
TeleportController.ts 保留门面;提供本地请求接管和跨图交接接口
TeleportDefine.ts / TeleportModel.ts 独立三策略定义;不可变请求快照;pending 与 committed 区分
TeleportSameSceneFlow.ts 编排三模式,不再一律启动流送;接入共享提交和收敛
TeleportGroundProbe.ts 准备期纯查询;实际角色接地/候选位置契约分离
TeleportPresentation.ts 只管理遮罩/Loading/淡变的 own token 与真正显露条件
TeleportTransitionFlow.ts 删除无缝无条件流送路径;表现升格独立于安全完成
TeleportSequenceFlow.ts / TeleportSeq3Binder.ts 只适配目标事务/角色控制权交接,不改演出资源和叙事时序
TeleportV2Flow.ts 保留独立实现,只适配共享边界;本轮为职责与关键路径扫描,非逐行演出审计
TeleportEntityBufferController.ts 明确缓存所有权和 TTL 后回放仍须校验,不充当上行屏障
LevelEnterConfig.ts 保留配置适配,不顺手改配置语义
TsTeleportLibrary.ts / TeleprotLoadScene.ts / TeleportView.ts 空壳或注释草稿,不纳入现行运行链,不顺手清理
关联路径组 必须处理的边界
Module/CombatMessage/CombatMessageController.ts;World/Entity/Common/BaseMoveSyncComponent.ts 提前移动、非 Enabled 直写、事件语义、WithStreaming 取消与提交结果
World/Entity/Common/ComplexMoveSyncComponent.ts;Common/Move/MoveSyncReporter.ts 普通/强制采样/最终打包屏障;调用点只在必要时最小适配
World/Entity/MoveSync/MoveSyncController.ts 与当前事务冲突的延迟位置队列清理或作废
World/Entity/Character/SceneItem/FallingRebornController.ts 只迁移技术落位,修正防重入生命周期与备用点验证
World/SceneLoading/Commands/SceneLoadingCommandHelper.ts;SceneLoadingTeleportCmd.ts 分离纯准备与场景副作用;结果和 Reset 仅作用于自身 executor
World/SceneLoading/StreamingSourceInfo.ts;相关 NewScene/Move/WaitWp 命令 目标源 owner、保活和主源覆盖确认;协调现有场景预加载
SceneLoadingAfterCmd.ts;SceneLoadingWpMapCmd.ts;实体创建/激活链 保留跨图握手;创建前保护、创建后绑定与验证;不阻断 EndClientLoading→Seq3
BaseActorComponent.ts;BaseCharacterComponent.ts;MovementMiddlewareComponent.ts;CharacterPlacementQuery.ts 优先复用查询与原生结果;必要适配限定本次落位调用,不改变所有普通移动语义

关键证据定位(本次读取行号)

11. 先做最小实测,再展开实现

以下均为未验证。先用一个同图 UI load+一个坠落黑屏代表链路跑通,再测跨图创建与 Seq3 交接;没有证据不把勾选项标为通过。

难点/返工源 验证方式 通过标准
先流送后移动 慢速目标流送,记录 Actor、主源、目标源和提交帧 准备期 Actor 留在原区域;碰撞准备好才提交;目标源直到主源接住才释放
普通黑屏不改 MovementMode 站立、走动、坠落入口分别记录模式调用、保护源、物理 Tick 无普通黑屏主动模式设置;落位后自然获得新接地/Grounded/NotMoving
Idle 和 Mesh 不是同一完成信号 低帧率、角色差异下记录逻辑态、骨骼/模型偏移和遮罩首个可见帧 首个显露帧已站稳且模型无从高处落下;Reset 只置标志不能被误记为完成
乱序/重复/取消 交换通知顺序,连续 A→B,Bail A,延迟触发 A 的 timer/Promise A 不再位移、不关 B 遮罩、不释放 B 目标源;每个事务提交/完成至多一次
上行漏口 准备期触发普通移动、技能强制采样、最终组包和回放 没有“新 version+旧位置”;恢复首包是目标位置,无残留速度/旧队列
源点在空中 坠落请求延迟响应、目标未加载、技能/Root Motion 冲突 等待期不继续失控下坠、不重复处罚、不死锁;保护能按 owner 释放
跨图创建窗口 新建/复用角色、慢资产、无缝换落点、创建失败 首个物理 Tick 不掉入空场景;绑定后再验证;LoadDone 与实体创建无等待环
Seq3/V2 交接 EndClientLoading 触发、演出取消、换装、归还角色 共享层不抢 Binder 的位置;Seq3 能启动;恢复同步前样本已清理

日志统一带“传送”前缀,记录 generation、version、world/level、entity、策略、阶段、源/目标/实际位置、ground/pose/mesh 证据、资源 owner 和失败原因;只在阶段变化或聚合告警时输出,避免每帧刷屏。模型验证若缺 Native 可观测接口,先交动画团队确认,不扩大客户端 TS 改动范围去猜。

12. 通过验证后的落地顺序

  1. 事务基础:收包接管、单次提交、取消校验、上行屏障与资源 owner 一起落地,先堵住旧旁路。
  2. 三种同图:拆纯查询/目标流送/Settling,接入表现显露条件;普通黑屏不改模式,无缝不默认遮挡。
  3. 坠落与边界:迁移技术段,保留处罚请求/安全点/完成事件,去掉“固定时长代表安全”的依赖。
  4. 跨图:创建前保护和创建后验证,目标源交接,Seq3/V2 边界适配;握手含义不变。
  5. 回归与收口:逐项实机证据达标后删除被替代路径,不长期保留两套并行落位实现。

每批改动前记录用户已有差异,只回退本批内容,不整文件覆盖他人修改。代码 CRLF、短注释;精准 eslint --fix 后执行 npm run tsc-native 并报告结果。静态检查通过不等于实机通过。

最低回归矩阵

同图三模式 × 已加载/未加载/非法点;走动/站立/空中/技能;窄平台/斜坡/动态支撑;不同角色与低帧率;坠落本地安全点/个人复活点/备用点;连续请求/倒序/取消/重连/销毁;同 WP 换落点/跨地图新角色;普通 Seq 与 V2;目标源预加载争用。未支持的特殊姿态必须明确交还 owner,不得静默当作普通 Idle。

13. 本次审阅只需确认的产品规则

  1. 目标未加载时是否允许升格:建议无缝/黑屏显式切 UI load,坠落也遵循该规则;不允许则保留故障等待而不强移。
  2. “范围内”的定义:建议“目标已加载且可落位”为硬前提,距离只决定表现偏好,不沿用 100m 作安全保证;如有策划距离限制,作为额外规则明确。
  3. 跨图纳入本次整体方案、后阶段实施:建议同意;不重写 Seq3/V2 演出,不更改服务端握手。

已有“不自动退登、不超时伪成功”和“普通黑屏不改 MovementMode”要求继续有效。审阅通过后先执行第 11 节技术验证,关键难点全部获得证据再展开实现;当前交付仅为方案和站点文档。