下载 App
资源策略从“全量引用 + 全量预下载”切换为“增强引用 + DWP”
结论
目前 300/300MB 的主要原因已经明确,不是网络偶发问题,而是同时存在两层“全量加载”:
- 构建配置要求所有资源入包,并在启动前全部下载
- 客户端启动后,又主动创建了所有遭遇动画的 152 张纹理
所以当前行为本质上是:先把整个资源仓库下载完,再一次性把大量遭遇动画解码进内存。


1. 第一根因:配置为“全量引用 + 全量预下载”
当前配置是:
- groups.default = ["**"]:assets/、scripts/ 下所有资源全部进入发布包
- preload_groups = ["default"]:这个组里的所有资源在启动前全部下载
位置:
- .project/resources.json:4
- .project/resources.json:8
最近构建日志也明确提示:
构建策略:全量引用——所有本地资源入包
预下载:启用——组内资源启动时预先下载
这正是界面显示 300/300MB 的直接原因。


2. 当前资源体积构成
我统计了 assets/,不包含 .meta:
| 资源类别 | 文件数 | 磁盘体积 |
|---|---|---|
| PNG 图片 | 247 | 116.67 MiB |
| MP4 视频 | 40 | 103.53 MiB |
| 合计 | 287 | 220.20 MiB |
发布端显示接近 300MB,通常还会包含打包元数据、脚本依赖、字体、资源索引等。虽然与本地裸文件体积不完全一致,但量级是吻合的。
最大的冗余来源:原始 MP4
assets/video/ 占了 103.53 MiB。
这些视频主要是生成遭遇动画 PNG 时使用的原始素材,例如:
- 爷叔填单.mp4:4.55 MiB
- 贾跃亭汽车.mp4:4.29 MiB
- 打新中签.mp4:4.26 MiB
- 雷股出清.mp4:4.24 MiB
- 壳太重了.mp4:4.17 MiB
目前游戏运行时使用的是提取后的 idle_1..4.png,没有发现脚本播放这些 MP4。由于资源配置是 **,这些制作源文件仍然被全部打包和预下载。
这部分理论上可以直接从运行包中裁掉约 103MB。
第二个冗余来源:冷库存档
assets/image/冷库/ 占 13.23 MiB。
冷库文件用于归档旧版本图片,不参与运行,但因为使用 **,也被加入包并启动下载。
第三个大头:遭遇动画
assets/image/遭遇怪物/:
- 152 张 PNG
- 磁盘体积:82.36 MiB
- 其中 148 张为 768×768
这些是有效游戏资源,不一定要从发布包删除,但不应该在进入游戏时一次性全部下载和解码。


3. 第二根因:启动时主动加载全部遭遇动画
所有遭遇动画资源路径都集中登记在:
- scripts/bullbear/Client.lua:203
- scripts/bullbear/Client.lua:212
- 一直延续到 scripts/bullbear/Client.lua:543
仅仅把路径写进 Lua 表,不一定代表运行时立即加载;但客户端启动时执行了下面的逻辑:
- 遍历所有 ENCOUNTER_MONSTER_VISUALS
- 遍历每种怪物的 4 帧
- 对每一帧调用 nvgCreateImage
- 同时开启 NVG_IMAGE_GENERATE_MIPMAPS
位置:
- scripts/bullbear/ClientCore.lua:94
- scripts/bullbear/ClientCore.lua:97
- scripts/bullbear/ClientCore.lua:99
这意味着即便只把 .project/resources.json 改成 DWP,游戏启动后仍会立即请求全部 152 张遭遇图。
因此,只改预下载配置还不够,要同时改成遭遇动画按需创建。


4. 内存压力也很明显
152 张遭遇图片在磁盘上是 82.36 MiB,但 PNG 进入 GPU 后要按 RGBA 展开。
当前估算:
- 不带 mipmap 的 RGBA 解码体积:约 337 MiB
- 启用 mipmap 后再增加约三分之一
- 遭遇动画纹理可能接近 450 MiB GPU 内存
这还没有计算:
- 大厅背景
- 游戏底图
- 电视图片
- 牌框
- 状态图标
- UI 渲染目标
- 引擎自身纹理
所以当前问题不仅是下载慢,还可能带来:
- 手机内存压力
- GPU 显存压力
- 首次启动卡顿
- 纹理解码峰值
- 低端设备闪退风险
而一轮实际上只显示一个遭遇的 4 帧。只保留当前 4 帧时,遭遇纹理内存大约可以从四百多 MiB 降到十几 MiB。


推荐优化顺序
第一优先级:启用 DWP,取消全量启动预下载
目标是把资源策略从:
全量引用 + 全量预下载
改为:
按引用构建 + 媒体资源按需下载
理想状态:
- Lua、JSON、XML 等必要脚本和配置启动前准备好
- 大厅首屏图片只加载大厅需要的资源
- 遭遇图片在即将出现对应牌面时加载
- 未使用的原始 MP4、冷库、旧素材不进入运行包
这是收益最大的一步。
但要注意:如果只取消 preload_groups,而不处理 ClientCore.lua 的全量 nvgCreateImage,启动后仍会立即触发 82MB 遭遇图下载。
所以配置与运行时懒加载应一起考虑。


第二优先级:把制作源文件排除在运行资源目录之外
建议把资源分成两个概念:
运行时资源
留在 assets/:
- 当前大厅背景
- 游戏底图
- 角色头像
- 状态图标
- 技能图标
- 当前使用的遭遇 PNG
- 运行时需要播放的视频和音频
制作源文件和归档
不应进入 asset_dirs:
- 提取 PNG 用的原始 MP4
- 旧版动画帧
- 冷库存档
- 未采用的生成图片
- 中间处理结果
当前最明显的是:
- assets/video/:约 103.53 MiB
- assets/image/冷库/:约 13.23 MiB
只排除这两项,运行资源裸文件就能从约 220MB 降到约 103MB。
不一定要删除这些文件,只要让它们不参与构建即可。保留在项目中做美术源文件归档没有问题。


第三优先级:遭遇动画改成按牌面加载
推荐的生命周期是:
- 进入大厅:只加载大厅和选角资源
- 进入休整:加载休整界面、电视、航线资源
- 服务端确定下一张牌:提前下载这张牌对应的 4 帧
- 进入遭遇:创建这 4 张 NanoVG 图片
- 遭遇结束后:
- 可以保留最近少量动画作为缓存
- 或释放旧动画,只保留当前/下一张
- 局终:按需加载结算航海图
这样每次遭遇通常只需要下载大约 2~3MB,而不是首屏下载全部 82MB。
为了避免切换时看到占位图,可以在休整阶段或服务端下发下一事件后提前下载,而不是等到遭遇已经显示才开始。


第四优先级:降低遭遇帧分辨率
目前 148 张遭遇图片是 768×768。
是否需要这么高,要看它们在最终屏幕上的实际显示尺寸:
- 如果怪物大多数只显示在约 200~350px
- 那么 768×768 通常偏大
- 手机横屏下更可能存在明显浪费
可以考虑:
| 使用环境 | 建议候选 |
|---|---|
| 主要显示约 200~300px | 384×384 |
| 需要兼顾高 DPI | 512×512 |
| 怪物确实会放大到接近全屏 | 保留 768×768 |
如果全部从 768 降到 512:
- 像素数量降到原来的约 44%
- 解码内存可由约 337 MiB 降到约 150 MiB
- PNG 下载体积通常也会显著下降
不过这一项应该排在 DWP 和懒加载之后。因为即使保持 768,只按需加载当前 4 帧,问题也已经会大幅缓解。


第五优先级:检查 mipmap 是否必要
当前所有遭遇动画都使用:
textNVG_IMAGE_GENERATE_MIPMAPS
见 scripts/bullbear/ClientCore.lua:97。
如果遭遇怪物始终以接近固定尺寸进行 2D 展示,并没有从极远处缩小到很小,mipmap 的收益可能有限,却会:
- 增加约三分之一纹理内存
- 增加纹理创建成本
- 增加初始化工作量
但是否关闭需要实机观察缩放时的清晰度与闪烁,不能仅凭体积直接决定。


建议实施方案
方案 A:低风险快速优化
适合先验证加载时间:
- 原始视频和冷库不参与运行包
- 取消全量预下载,启用 DWP
- 遭遇动画从“启动时全部创建”改成“当前牌面才创建”
- 保持现有 PNG 尺寸和画质不变
预计效果:
- 发布包减少至少约 116MB
- 首屏不再显示 300MB 全量下载
- 大厅可能只需要下载十几 MB 以内的资源
- 遭遇资源随后按每张牌约 2~3MB 加载
- GPU 纹理峰值大幅下降
这是我最推荐的第一阶段。
方案 B:进一步压缩
方案 A 稳定后再做:
- 768×768 遭遇帧评估降到 512×512
- 判断是否取消 mipmap
- 评估 4 帧合并图集
- 压缩大厅和电视等大图
- 统计每个界面的实际下载量和纹理内存
图集主要减少文件数量和资源请求,不一定明显减少解码后显存;真正降低显存的仍然是分辨率和按需释放。


验收时应看什么
优化后不能只看“能进入游戏”,建议检查以下指标:
- 构建日志
- 不再出现“全量引用”
- 不再出现“预下载 default 全组”
- 冷启动
- 清缓存后进入大厅的下载量
- 热启动
- 第二次进入是否复用缓存
- 首个遭遇
- 是否只下载当前怪物的 4 帧
- 连续多局
- 内存是否持续增长
- 低端手机
- 是否仍有纹理创建卡顿或闪退
- 资源完整性
- 随机抽到任意牌面时,对应动画都能正常出现


最核心的判断
当前不是“图片太多”这么简单,而是:
制作源文件、运行资源、冷库存档全部放进同一个全量预下载组;客户端还在初始化阶段一次性创建所有遭遇纹理。
优先解决“资源边界 + DWP + 遭遇懒加载”,比先压缩每张图片更有效。全程仅分析,没有修改代码或配置。
已完成方案 A:低风险快速优化。
已完成方案 A:低风险快速优化。
已实施
- 将资源策略从“全量引用 + 全量预下载”切换为“增强引用 + DWP”:
- .project/resources.json:4
- 构建根资源改为 scripts/**
- preload_groups 已清空
- 原始 MP4、冷库及其他未引用素材不会再进入运行包。
- 取消启动时一次性创建全部 152 张遭遇动画纹理。
- 收到当前牌面 SHOW_EVENT 后,只下载并创建对应的 4 帧:
- scripts/bullbear/ClientCore.lua:41
- scripts/bullbear/ClientCore.lua:817
- 切换牌面、离开玩法阶段或客户端停止时:
- 取消旧下载
- 调用 nvgDeleteImage 释放旧纹理句柄
- 只保留当前遭遇的四帧
- scripts/bullbear/ClientCore.lua:26
- scripts/bullbear/ClientCore.lua:184
- 下载过程中继续显示既有海星占位,不阻塞牌面流程:
- scripts/bullbear/ClientRender.lua:44
构建结果
最新构建日志确认:
text构建策略: 增强引用 预下载: 未启用 扫描本地资源: 729 个文件 发现可达资源: 58 个 分组总资源: 59 个 项目资源大小: 93.24 MB
此前本地 assets/ 裸资源约为 220.20 MiB;当前构建统计为 93.24 MB。更重要的是,这 93.24MB 不再要求进入游戏前一次性下载,而是由 DWP 按实际使用加载。
验证
- Lua LSP:0 Error
- 官方 UrhoX 多人构建:成功
- 多人配置保持:
- 后台匹配开启
- free_match_with_ai
- 4 人
- 3 秒 AI 补位
- 秒开模式开启
- 未执行 Git 提交。
建议实机验收
请清除游戏缓存后重点验证:
- 首次进入大厅不再显示 300/300MB。
- 进入第一张遭遇牌时,海星占位短暂出现后替换为对应动画。
- 连续切换不同遭遇,动画都能正确显示。
- 断线重连到 PLAYING/REVEAL 时,当前遭遇动画能重新加载。
- 连续玩多局后内存不持续上涨。



