KBE 参考原则与 ECS 兼容取舍
这篇文档不是讲某一个具体模块,而是给 Apollo 后续所有架构设计定一个总原则:
Apollo 可以参考 KBE,但不能照搬。
这句话不是泛泛而谈,而是必须落到每个设计点上的工程约束。
尤其要明确一点:
KBE/BigWorld的很多核心概念- 和现代
ECS / 数据导向 / cache-friendly 批处理
并不是天然一致的。
如果这个前提不先说清楚,后面的设计就很容易出现两种问题:
- 要么机械照搬 KBE,结果和 Apollo 想要的现代模块化架构冲突
- 要么只讲 ECS,不承认 MMO 分布式世界和在线对象模型的真实约束
一、先说结论
Apollo 对 KBE 的正确态度应该是:
参考它解决问题的方式不照搬它的历史实现形态保留对 ECS/数据导向友好的空间每个设计点都必须写清楚理由、优点、代价和不选方案
更准确地说:
Apollo 应该吸收 KBE 的分布式世界经验,而不是复制 KBE 的全部对象和运行时风格。
二、为什么不能照搬 KBE
1. KBE 解决的是特定时代和特定问题
KBE/BigWorld 的核心强项在于:
- 大世界分布式空间
- Proxy / Base / Cell 对象分层
- Witness / Ghost
- 实体远程调用
- 脚本驱动业务
这些能力今天仍然很有价值。
但 KBE 的很多具体实现也带有明显时代背景:
- Python 深绑定
- 面向对象实体模型非常重
- 分布式对象语义优先于数据导向语义
Apollo 没必要把这些实现形态原样复制下来。
2. Apollo 的目标比 KBE 更宽
Apollo 不是只服务一种:
- BigWorld MMO
而是要支持:
- 轻在线
- 房间制
- 普通 MMO
- BigWorld 增强态
这意味着 Apollo 必须保留:
- 更强的模块化
- 更清晰的分层
- 更灵活的业务域装配
3. 现代工程目标已经不同
Apollo 现在追求的不只是:
- 跑得起来
还包括:
- 可模块化装配
- 可分层扩展
- 可脚本后端替换
- 可运维治理
- 可平台能力复用
这要求设计必须比 KBE 更显式地写清取舍。
三、KBE 和 ECS 的主要冲突点
这里必须明确写出来,不然后面容易默认它们是天然兼容的。
四、冲突点 1:对象中心 vs 数据中心
KBE 更偏对象中心
KBE 的核心视角是:
- Entity 是中心
- BaseEntity / CellEntity / Proxy / Ghost 都是对象
- 远程调用围绕对象引用展开
ECS 更偏数据中心
ECS 的核心视角是:
- 数据组件是中心
- 系统批量遍历组件
- 对象身份是次级概念
设计结论
Apollo 不能把整套 runtime 全部做成纯 ECS,也不能把所有东西都做成重对象模型。
更合理的方式是:
- 在线身份、路由、分布式世界边界用对象语义
- 战斗、属性、局部模拟、批处理热点保留 ECS/数据导向空间
五、冲突点 2:远程实体调用 vs 批处理系统调用
KBE 更强调 EntityCall
也就是:
- 调某个实体
- 调某个方法
- route 到某个宿主
ECS 更强调系统级批量处理
也就是:
- 一批 Position + Velocity
- 一次系统更新
设计结论
Apollo 应该保留两条通路:
RemoteEntityCall- 解决跨宿主、跨进程、跨空间对象语义
System Batch Update- 解决局部高频计算
不能用一条路径强行替代另一条。
六、冲突点 3:重实体生命周期 vs 轻量组件热路径
KBE 的实体生命周期更重
例如:
- enter world
- leave world
- get witness
- migration
- backup
ECS 热路径更希望轻量
例如:
- 位置更新
- 属性结算
- 战斗系统迭代
设计结论
Apollo 应该分层处理:
PlayerAnchor / AvatarEntity / GhostReplica- 维持对象生命周期
Movement / Combat / Attribute- 允许内部采用 ECS 或数据导向结构
也就是说:
- 外层对象模型
- 内层系统可数据导向
七、冲突点 4:脚本对象语义 vs 数据导向内核
KBE 非常强调:
- 脚本实体
- 脚本方法
- 脚本属性
但如果把 Apollo 全部脚本化,就会和高频系统优化直接冲突。
设计结论
Apollo 应坚持:
- 脚本层负责业务规则
- 热路径内核保持 C++ 优先
这和前面的脚本层设计是一致的。
八、Apollo 参考 KBE 时应该保留什么
下面这些是 Apollo 应该重点吸收的。
1. Proxy / Base / Cell 分层思想
理由:
- 解决连接、长期状态、空间表现的生命周期分离
优点:
- 更适合重连、切图、分布式权威迁移
代价:
- 对象模型复杂度上升
为什么仍然值得保留:
- 这是 MMO 在线主链的核心约束,不是历史包袱
2. Witness / Ghost 思想
理由:
- 解决分布式空间下客户端可见世界连续性
优点:
- 支撑边界观察、迁移窗口、跨 partition 视图
代价:
- 复制链路和对象路由复杂度提升
为什么仍然值得保留:
- 这是 BigWorld 模式的核心能力
3. 实体定义统一层
理由:
- 属性、方法、复制、持久化、脚本接口必须统一
优点:
- schema 一致性高
代价:
- 前期抽象成本较高
为什么仍然值得保留:
- 不做这层后面会越来越散
4. 明确宿主边界
理由:
- 哪些逻辑在 Base、哪些在 World、哪些在 Gateway,必须有明确边界
优点:
- 架构稳定
代价:
- 初期需要更多设计约束
九、Apollo 不应照搬什么
下面这些不建议直接照搬。
1. 不照搬 Python-only 运行时绑定
理由:
- Apollo 要支持可替换脚本后端
优点:
- 降低语言绑定锁死风险
代价:
- 需要先做统一 Script ABI
2. 不照搬所有逻辑都围绕重实体对象展开
理由:
- 战斗、属性、批处理热点会被拖慢
优点:
- 给 ECS/数据导向保留空间
代价:
- 需要处理对象语义和系统语义并存
3. 不照搬 KBE 的进程全家桶作为默认起步态
理由:
- 不是所有项目都需要 BigWorld 模式
优点:
- 普通在线游戏和普通 MMO 更容易落地
代价:
- 要把增强层和默认层分清楚
4. 不照搬历史命名即真实语义
理由:
- 例如当前 Apollo 的
base-app和cell-app都有历史语义偏差
优点:
- 可以先校正语义,再决定目录名
代价:
- 过渡期需要文档特别清楚
十、Apollo 的推荐折中路线
Apollo 更合理的路线不是:
纯 KBE 对象模型
也不是:
纯 ECS 服务器
而是:
- 在线身份和分布式边界采用对象模型
- 高频局部系统允许 ECS/数据导向实现
- 通过分层把两者隔开
更具体地说
用对象模型承接的
ProxyPlayerAnchorAvatarEntityGhostReplicaWitnessContextRemoteEntityRef
允许 ECS/数据导向承接的
- movement subsystem
- combat subsystem
- attribute evaluation
- AI 局部状态更新
十一、后续文档必须统一采用的写法
这是最关键的要求。
Apollo 后续所有设计文档,建议都统一包含下面 6 段。
1. 设计目标
回答:
- 这个设计要解决什么问题
2. 参考来源
回答:
- 参考了 KBE 哪些概念
- 参考了哪些现代架构思路
3. 为什么这样设计
回答:
- 选择这种方案的直接理由
4. 优点
回答:
- 得到了什么收益
5. 代价与风险
回答:
- 复杂度、性能、维护成本增加在哪里
6. 为什么不选别的方案
回答:
- 为什么不照搬 KBE
- 为什么不做成纯 ECS
- 为什么不做成更简单但不够稳的方案
十二、对已有文档的直接要求
后续继续补文档时,建议统一增加这些内容:
为什么这样设计优点代价为什么不选其他方案
这样整套文档会从“结论集合”升级成“可辩护的架构设计稿”。
十三、结论
Apollo 的正确路线不是否定 KBE,也不是神化 KBE。
更合理的做法是:
- 参考 KBE 解决 MMO 分布式世界问题的经验
- 保留现代模块化、脚本抽象、平台能力分层和 ECS/数据导向空间
- 对每一个设计点都写清楚理由、优点、代价和不选方案
只有这样,这套整体框架才不会变成:
- 历史设计复制品
也不会变成:
- 失去 MMO 现实约束的空泛现代化重写
