游戏场景之大世界架构设计构想

架构拆分

  • 网关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 个实体的位置每帧都收一遍------

  • 带宽炸:每秒几十 MB,4G/WiFi 都扛不住

  • 但你根本看不见他们:大部分人在地图另一头,跟你半毛钱关系没有

解决方案

  • AOI(Area 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 A(DS-1),右半边 Zone B(DS-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/ delete(C++)或让 GC(C#/Java)去回收:

  • 频繁 new/delete​ → 内存像被咬了很多小洞(碎片),后来想申请一块大内存申请不到

  • GC 触发​ → 虚拟机暂停所有线程去扫垃圾,画面就卡住一帧 → 玩家:"又卡了?"

解决方案

对象池 + BufferGeometry 复用 + 异步分帧,绝不主线程 Instantiate

  • 对象池(Object Pool):Chunk 里的树、石头、怪物,别真 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)。

  • DS(Dedicated Server):专职跑游戏逻辑的服务器进程,不带渲染,纯算。

相关推荐
humors2213 小时前
支付宝游戏频道《灵画师》体验
游戏·介绍·体验·攻略·灵画师·试玩
HMS Core6 小时前
基于人体骨骼点识别与跟踪,实现低时延体感游戏
游戏·华为·harmonyos
AI分享猿1 天前
游戏原画与建筑灵感:AI图像生成如何服务前期设计
人工智能·游戏
饺子大魔王的男人1 天前
NAS还能挂机修仙?极空间部署XiuXianGame网页游戏教程
游戏
Tisfy1 天前
LeetCode 1406.石子游戏 III:递归(DFS+记忆化) / 递推(DP+原地滚动)
leetcode·游戏·深度优先·dfs·题解·博弈
@syh.2 天前
【贪心】矩阵消除游戏
算法·游戏·矩阵
njsgcs2 天前
北通蝙蝠2 摇杆漂移解决办法 校准+重启
游戏
qq_370773092 天前
Unity游戏xLua逆向实战:从SO版本识别到Lua脚本热替换全链路
游戏·unity·lua
噗噗夹的TA之旅2 天前
Shader 学习 21:自定义 Render Feature
学习·游戏·unity·c#·游戏引擎·图形渲染
网络研究院2 天前
一款利用人工智能将电子游戏翻译成任何语言的桌面应用程序
人工智能·游戏·工具·平台·翻译·软件