游戏场景之大世界架构设计构想 架构拆分网关Gate游戏服务Game登录服务Login中心服务Center全局服务Chat、Rank各部分都可以用一个单独进程或一个Actor来表示使用场景 必须用尺度决定了不得不拆开放世界 RPG / Action RPG原神、塞尔达、巫师 3、上古卷轴、黑神话方向原因几 km² ~ 几十 km² 连续地图全装内存不可能 → 必须 Chunk 流式生存沙盒 / 建造类Rust、方舟、我的世界理论无限、幻兽帕鲁原因地图甚至程序化无限生成尺度没上限 → 必须空间分块 按需生成MMO现代派FF14虽然老但地图大、新倩女幽魂、逆水寒原因几千人同图 地图大 → 必须 AOI Zone 分片赛车 / 飞行开放世界极品飞车无界、微软飞行模拟原因移动速度极快飞行 200 km/h→ 预测加载 极低 Pop-in 要求 可选中小世界也能做但大世界是卖点大逃杀 / 百人吃鸡类PUBG、APEX地图其实不算特别大但 100 人 高速载具 → 也要 AOI 流式但比原神那种真·大世界轻FPS / TPS 开放世界地平线西之绝境、孤岛惊魂 —— 单图大但人不太多纯 PvE服务端压力小客户端流式压力大❌ 一般不用MOBA王者、LOL→ 单局一张小地图3 条路没必要传统 FPS 竞技CS2、OW 占点→ 图小、人数固定卡牌 / 回合制 RPG → 根本没有走地图这件事技术选型客户端后端核心问题前置语境大世界和普通关卡的差别普通关卡一张地图 200m×200m全部塞内存所有玩家互相看得见服务端一帧把所有人的位置广播给所有人——没问题因为总量小。大世界8km×8km 甚至更大几千玩家同时在地图本身几百 MB 到 GB 级。于是下面 5 个问题一个个蹦出来。视野同步怎么做到不丢也不炸起因你站在大世界里地图上其实有 2000 个玩家、3000 个怪。如果你的手机/电脑要把这 5000 个实体的位置每帧都收一遍——带宽炸每秒几十 MB4G/WiFi 都扛不住但你根本看不见他们大部分人在地图另一头跟你半毛钱关系没有解决方案AOIArea of Interest兴趣区域服务端给每个玩家划一个我关心这个范围只把范围内的事发给他。类似你只订阅自己周围的新闻。AOI学习笔记九宫格把地图切成象棋盘一样的格子你在中间那格服务端只发你 上下左右 四个对角这 9 格里的实体给你。Diff增量你从格子 A 走到格子 B不用重新发你周围所有人只发刚才那 9 格里没了谁、新进了谁——这就是上一轮伪代码里 leave/ enter的由来。跨 Chunk / 跨 Zone 怎么无感​起因客户端把地图切成了 Chunk比如 128m×128m 一块。你走路1 号 Chunk → 2 号 Chunk本来是内部小事但有两件事会露馅客户端侧2 号 Chunk 还没 Load 完你眼前一片空白 → “Loading 感”服务端侧2 号 Chunk 属于另一个 DS 进程Zone B你走过去如果让客户端断线重连 → 屏幕中间一个正在连接… → 体验崩了玩家期待的是骑马从草原冲进森林不停、不卡、不 Loading。解决方案客户端 Chunk 边界重叠 服务端 DS 切流协议Chunk客户端地图切块的基本单位流式加载/卸载的最小颗粒。Zone / DS 分片服务端服务端把大地图切成几块每块跑一个 DS 进程。比如左半边 Zone ADS-1右半边 Zone BDS-2。热迁移 / 切流玩家从 Zone A 走到 Zone B 时服务端把这个玩家的状态快照从 DS-1 拷到 DS-2客户端悄悄把网络连接从 DS-1 切到 DS-2——你还在骑马完全不知道背后换了台服务器。高速移动 Chunk 来不及 Load 怎么办​起因你走路 → Chunk 加载来得及人速 ~6m/s。你骑马 → 还行马速 ~15m/s。你开载具 / 滑翔翼 → 50–80 m/s。流式加载的逻辑是你走到哪、加载到哪。如果你速度太快等你踩到 Chunk 边界时那个 Chunk 的美术资源地形、树、房子还在硬盘→内存→GPU 的路上 → 你眼前突然地没刷出来掉下去了或者树啪一下冒出来。解决方案预测加载速度向量 × 系数 低模占位预测性预加载Predictive Streaming不光加载你脚下这格还加载你面朝方向再往前 N 格。类似你开车导航不光显示你车轮底下还显示前面 500m。速度向量 × 系数Client 拿你的朝向 速度算出你 2 秒后会到哪提前发 Load 请求。低模占位Proxy / Impostor真资源没到之前先摆一个超低模的假房子顶着资源到了再换真身——玩家不至于看到空气。内存碎片 / GC spike​起因你玩游戏时偶尔会突然卡一下0.5 秒画面不动——这叫 Spike。大世界里你走一步就可能有旧的 Chunk 卸载 → 几百个 GameObject 销毁新的 Chunk 加载 → 几百个 GameObject Texture Mesh 新建如果每次都真的 new/ deleteC或让 GCC#/Java去回收频繁 new/delete​ → 内存像被咬了很多小洞碎片后来想申请一块大内存申请不到GC 触发​ → 虚拟机暂停所有线程去扫垃圾画面就卡住一帧 → 玩家“又卡了”解决方案对象池 BufferGeometry 复用 异步分帧绝不主线程 Instantiate对象池Object PoolChunk 里的树、石头、怪物别真 Destroy丢回池子里下次拿来改个坐标复用 → 零分配GC 就安静了。Buffer / Mesh 复用地形、植被的 GPU 资源也别反复创建销毁池化。万人同图服务端怎么扛​起因假设 8km×8km 大世界在线 1w 人每人带宠物/坐骑地图上还有 2w 个野怪、采集物——3w 实体。如果一个服务端进程全扛每帧要遍历 3w 实体算 AI、算物理AOI 广播就算九宫格剪过CPU 还是爆一个进程崩 → 全图 1w 人掉线解决方案空间分 Zone AOI 剪枝 云原生按 Key 闪回Zone 分片Space Sharding把地图按空间切成几块每块一个 DS 进程各管各的 → 问题 2 里的跨 Zone 热迁移就是为了把这个切分藏起来不让玩家看见。云原生扩缩容大世界白天 2k 人在线、晚上 1w 人Zone 数可以动态加比如把原来 1 个 Zone 拆成 2 个——但要配合按 Key 分片的数据层Redis/Mongo 按 Zone ID 或 Player ID hash。DSDedicated Server专职跑游戏逻辑的服务器进程不带渲染纯算。