第九章

客户端架构与资源管理

第八层 · AB包/按需加载/热更新 800MB 游戏包怎么瘦身,进对局不再卡

一、三个痛点:包太大、加载慢、更新难

王姐的吐槽总结成三个技术问题:

云间对决的三个痛点:
  ① 包太大:800MB(手机下载要半天)
     → 原因:所有资源一股脑打进了安装包
  ② 进对局卡:点"开始对战"要加载 10 秒
     → 原因:对战场景资源没提前准备
  ③ 更新难:改个英雄数值,玩家要重新下载整个包
     → 原因:没有热更新机制

  这三个问题,都属于"客户端架构 + 资源管理"的范畴
  也是专业游戏开发(相对 demo)的分水岭

"'能玩'和'能上线'之间,隔着客户端架构这道坎。 资源管理做不好,游戏做得再好也上不了线。"


二、场景管理与模块化:把游戏拆成"模块"

"先讲架构思想:模块化(Modularity)。"老周说,"游戏不能是一坨代码 + 一坨资源,要按'功能域'拆开。"

模块化架构(云间对决):
  ├── Core(核心框架):场景管理、事件总线、配置
  ├── UI(界面):HUD、大厅、结算面板
  ├── Battle(对战):战斗逻辑、英雄、技能
  ├── Network(网络):连接、同步、重连
  ├── Audio(音频):BGM、音效
  └── Resources(资源):资源加载、对象池

  好处:
    各模块独立开发、独立测试
    模块间通过接口通信(低耦合)
    新英雄/新玩法 = 新增模块,不动核心

  场景管理(Scene Management):
    启动场景(Logo)→ 大厅场景 → 加载场景 → 对战场景
    切换场景 = 卸载旧场景资源 + 加载新场景
    场景加载要"异步"(不卡住主线程)

  架构模式:
    MVC / MVVM(界面与逻辑分离)
    单例(GameManager、AudioManager)
    事件总线(模块间通信,松耦合)

"模块化 + 场景管理是游戏客户端的'骨架'——一个清晰的骨架,让你加功能时不会'拆东墙补西墙'。代码的'可维护性',从这里来。"


三、资源加载:按需加载,不一股脑塞包

"解决 800MB 问题,核心是资源加载策略。"老周说:

资源加载三策略:
  ① 初始包(包内资源):只放"必装"资源
     - 启动、大厅、新手教程、常用 UI
     - 约 100-200MB
  ② 按需下载(进游戏后下载):
     - 英雄皮肤、语音包、高清特效
     - 用到才下载(玩家看不到的别下)
  ③ 分包(按模块打包):
     - 对战地图分包、英雄分包
     - 进哪局下哪局(地图分包)

  加载方式(Unity):
    同步加载:加载完才能继续(会卡,少用)
    异步加载:后台加载,加载完回调(推荐)
    Resources.Load / AssetBundle(Unity 的打包格式)

  异步加载示例(伪代码):
    async def load_battle_scene():
        # 显示"加载中"进度条
        show_loading_screen()
        # 异步加载资源(不卡住 UI)
        await load_bundle("map_yunjian_gorge")
        await load_bundle("heroes_pack")
        # 加载完成,进入对局
        enter_battle_scene()

"资源加载的黄金法则:'用多少、下多少;什么时候用、什么时候下'。 800MB 不是一次全塞给玩家,而是拆成'必装的 + 按需的'。王者荣耀的安装包也不大,但各种资源都是'分阶段下载'。"


四、AssetBundle 与资源依赖:打包的艺术

"Unity 的资源打包核心:AssetBundle(AB 包)。"老周说:

AssetBundle(AB 包):
  把资源打包成"可独立下载的文件块"
  每个英雄一个包:hero_001.ab(图片+动画+音频+配置)
  每张地图一个包:map_001.ab

  ┌─────────────────────────┐
  │ 主包(安装包)            │
  │  ├── 启动 + 大厅 + UI    │
  │  ├── 公共资源(字体/通用)│
  │  └── 资源清单(Manifest)│
  ├─────────────────────────┤
  │ 按需包(运行时下载)       │
  │  ├── hero_001.ab(英雄1)│
  │  ├── hero_002.ab(英雄2)│
  │  └── map_001.ab(地图1) │
  └─────────────────────────┘

  资源依赖管理:
    A 包引用了 B 包里的贴图 → 加载 A 前先加载 B
    → 用"依赖关系表"管理(打 AB 时自动生成)

  版本管理:
    每个 AB 包带版本号/哈希
    服务器有新版本 → 客户端下载差异部分(增量更新)

"AssetBundle 是 Unity 手游资源分发的标准方案——把资源拆包、按需下载、增量更新。'800MB 瘦身'和'热更新'全靠它。"


五、热更新:改内容不用重装 App

"更新难的问题,靠热更新(Hot Update)解决。"老周说:

热更新(Hot Update):
  含义:不重新安装 App,下载资源/代码更新
  两类热更新:
    ① 资源热更(主流):替换 AB 包
       - 改英雄数值、换皮肤、换地图 → 下新 AB 包
       - 苹果 App Store 允许(资源不审核)
    ② 代码热更(敏感):替换脚本
       - 改玩法逻辑 → 下新代码
       - 苹果对"代码热更"有限制(合规风险!)
       - 方案:Lua/ILRuntime 等脚本方案

  热更新流程:
    启动 → 查服务器版本清单
    → 发现新版本 → 下载增量包(只下变化的部分)
    → 校验 → 应用 → 下次启动生效

  版本管理:
    版本号(1.0.0 → 1.0.1)
    资源清单(每个 AB 包的哈希值)
    服务器存最新清单,客户端对比差异

  云间书店方案:
    英雄数值平衡调整 → 资源热更(AB 包)
    重大版本 → 商店更新 + 热更组合
    合规:代码热更慎用(过审风险)

"热更新是手游'活下去'的关键能力——没有它,修个 bug 都要重新上架审核(iOS 审核要几天到几周)。有了它,今天改的数值,玩家明天打开就生效。"


六、启动优化与进度条体验

"除了资源,加载的'体验'也重要。"老周说,"玩家最讨厌'卡死'的感觉。"

加载体验优化:
  ① 异步加载 + 进度条:让玩家看到"在动"
  ② 分阶段加载:
     先加载必玩的(大厅)
     再后台预加载(对战地图,提前下载好)
  ③ 预加载(Preload):
     玩家在大厅时,后台悄悄下载/加载对战资源
     → 点"开始对战"时秒进
  ④ 防卡顿:
     不在主线程做重活(资源加载异步)
     高峰期控制同时加载数量

  进阶:流式加载(Streaming)
    地图边玩边加载(大地图分区加载)
    → 类似开放世界的"无缝大地图"思路

"加载体验 = 手游的'第一印象'——很多玩家因为'加载太久'直接卸载。进度条、预加载、异步加载,都是让'等待'变得可接受的技巧。"


七、章末:老周的第八层总结

第八层:客户端架构与资源管理
├── 模块化:按功能域拆(Core/UI/Battle/Network/Resources)
├── 场景管理:异步切换、加载不卡主线程
├── 资源加载三策略:初始包 + 按需下载 + 分包
├── AssetBundle:资源拆包、依赖管理、版本控制
├── 热更新:资源热更(主流)+ 代码热更(合规慎用)
├── 加载体验:进度条、预加载、分阶段
└── 核心:用多少下多少,什么时候用什么时候下
下一章预告:
  包小了、加载快了、能热更了——但玩家进游戏一看:
  界面丑、操作不顺、没打击感!
  —— UI 交互与表现:摇杆、血条、伤害飘字、打击感。

"小陈,800MB 瘦身到 150MB,进对局 10 秒变 2 秒,数值调整当天热更生效——王姐满意了。"老周说,"但游戏上架前还有个'玩家骂街'的地方:界面和手感。摇杆顺不顺、技能按钮好不好按、血条清不清楚、打击感爽不爽——下一章,UI 交互与表现,让游戏'好看又好用'。"

✌ 语言