角色对称:Client 与 DS 应共享契约,不应共享启动时序
自动关联目录:角色对称:Client 与 DS 应共享契约,不应共享启动时序
核心判断:Client 与 DS 应在身份、命令、快照和场景事实上对称,但 UE 为两者提供依赖的时机不同;强行复用同一启动路径,会把生命周期偶然性写进业务协议。
一、业务冲突
同一玩法需要 Client 预览、联网客户端和 DS 解释一致的内容与状态,但三者的 World 建立方式并不相同。ClientTravel 后网络驱动、GameInstance 和场景依赖会分阶段就绪;DS 的命令行输入更早可用,却又必须等监听端口真正绑定后才能对外宣告 Ready。
二、实际实现
实际工程把 Client VM 与 Server VM 交给不同的 World 角色宿主管理,场景值状态和协议保持共用。客户端采用延迟引导:地图加载完成后继续等待网络与会话事实齐备;DS 可以较早完成 VM、场景和 Actor 的确定性构建,但把外部 Ready 信号推迟到 NetDriver 端口确认之后。
共享接口只表达少量冷启动能力,没有把两个宿主压进一个巨型基类。一次实际路由问题也说明了角色绑定的重要性:玩家加入事件若落到默认或编辑 VM,而不是权威 VM,代码能运行,语义却完全错误。
三、值得保留
“数据与协议对称、生命周期适配分离”是正确方向。它既允许共用确定性的领域逻辑,也保留了 Client 表现能力和 DS 无渲染约束。把外部 Ready 与内部早期构建分开,还避免为了修连接竞态而破坏 Actor 创建顺序。
四、结构性缺陷
如果角色宿主继续吸收场景、脚本、网络、物理和表现职责,它们仍会成为第二种全局管理器。通过扫描 World、进程静态标记或友元访问修补初始化空窗,只能绕过一次时序问题;调用方到处判断 NetMode、目标类型和模块是否存在,则会形成隐式能力矩阵。轻量接口也可能退化为“为了共用而共用”的空壳。
五、目标设计
共享的是显式角色上下文和端口,不是 Subsystem 具体类型:
struct RuntimeRoleContext {
RuntimeRole role; // Editor, Client, DedicatedServer
RuntimeScope scope;
CapabilitySet capabilities;
IProjectSnapshotSource& content;
IRuntimeVMHost& vm;
ITransport& transport;
IAuthority& authority;
IPresentation& presentation; // DS 注入 NullPresentation
};
TaskGraph ClientBootstrap(RuntimeRoleContext& ctx);
TaskGraph ServerBootstrap(RuntimeRoleContext& ctx);领域服务只消费端口和冻结的 CapabilitySet,不查询具体 World Subsystem。两个启动图可以不同,但都必须产出相同版本的运行时制品、作用域身份和协议能力证明。
六、取舍与验证
端口化会增加构造与测试装配代码,却能把角色差异从业务分支变成可验证依赖。契约测试应让同一内容快照和命令序列分别运行在客户端、DS 与无渲染轻量目标,比较领域结果;启动测试则分别覆盖 ClientTravel 依赖迟到、DS 端口迟绑、World 重建、角色误路由和能力缺失。对称性的验收对象是结果契约,不是回调顺序。