Unity 3D MMO RPG手游征服2GB设备之历程

文章目录

项目背景

场景

  • 1024*1024
  • 同屏200W面
  • 贴图1024
  • 自由视角

配置表

  • 1000+张配置表
  • C++内存加载350MB

角色

  • 同屏20人
  • 45个职业变种
  • 数万件时装
  • 模型面数3-5W面

业务系统

  • 3000+个界面
  • 200W+行非生成代码

资源

  • 10W+个AB

Unity版本

  • 2019

内存分布

  • Native Heap
  • Code
  • Graphic 图形内存
  • Unknown

Native Heap

Native Heap用来存放 C++层(引擎层) 的各种对象和资源数据。

  • Unity Engine 内部结构体、组件对象
  • 资源(Texture、Mesh、AudioClip 等)的 CPU 端数据
  • NativeContainer(如 NativeArray、NativeList 等)
  • Job System / Burst 编译代码用到的临时缓冲区
  • 底层系统调用(如物理系统、导航系统、动画系统)

Unknown

  • 华佗HybridCLR热更新的元数据

定位工具

Native内存

环境配置

  • Android Studio
  • Profile
  • Record Native Allocation

Code内存

环境配置

  • Android Studio
  • adb shell
  • run-as com.Unity.ClassicSponza cat /proc/11810/maps | grep libil2cpp.so

Lua内存

  • 递归遍历

关键指标

  • Native内存: 200MB
  • C++配置表: 30-40MB
  • Graphic: 100MB
  • Code: 100MB
  • Mono: 100MB
  • UnityNative: 200MB
  • 总计750MB

常见优化手段

纹理贴图

  • 图集
  • ASTC压缩
  • 关闭mipmap
  • 九宫格
  • 对称
  • 单行渐变
  • 单通道贴图
  • 关闭ReadWrite
  • 合理分辨率设置
  • 超采样压缩
  • streamingmipmap

模型

  • LOD
  • 优先级显示
  • 剔除余通道
  • 关闭ReadWrite
  • 名字版替代

场景

  • 公告板
  • LOD
  • 流式加载
  • 分层显示
  • 光照探针优化光照

特效

  • 贴图256
  • 总数限制
  • 粒子最大数量限制
  • LOD加载
  • 去重
  • 模型最大顶点数限制

动画

  • 压缩格式
  • 骨骼剔除
  • 属性剔除
  • 曲线压缩

音频

  • 压缩格式设置
  • 单通道
  • streaming
  • lazy加载

字体

  • 静态图集
  • 动态图集
  • ttf剔除

Shader

  • 变体剔除

优化案例

Mono内存

  • 去除字符串
  • gc替代缓存
  • 数据转移C++
  • 精简数据结构
  • 延迟加载
  • 精准卸载

代码元数据优化(Metadata)

IL2CPP在使用到某个类型时,会初始化这个类型完整的元数据,包括它的所有函数、接口、事件、属性、虚函数表等,并且一旦加载后就不会再释放。所以一个MMO游戏中,充分运行后,代码元数据占用的内存会非常高。

  • 排查泛型Template用的是否较多
  • 排查自动化生产的代码是否较多
  • 排查Lua生产的Wrapper代码是否较多
  • 删除无用插件、代码
  • 排查IL2CPP是否进行裁剪
  • 代码裁减调整至最高等级
  • link.xml

团结引擎通过深入分析,脚本代码实际运行时,通常只会用到很少的一部分元数据(反射、或者虚函数调用时访问)。例如,一个数组类型可能包含155个方法和25个虚函数,实现了6个接口,但实际运行时可能只会用到其中一小部分,导致大量内存被余加载。

因此,可以采用延迟加载策略。这意味着只有当游戏真正需要某个元数据项时,才会初始化和加载该数据。这种方法可以显著减少IL2CPP运行时的内存占用。

Unity后处理

  • 修改Urp的渲染管线,动态开关渲染特性,渲染特性的资源动态分配&释放
  • 重写后处理的框架,内存相关优化代码结构,避免反射进行无效访问
  • 动态加卸载用到的资源

配置表

背景

  • 1000张配置表
  • 内存占用极高
  • C#/Lua频繁访问

可选方案

  • 存储在单侧Lua/C#
  • 混合存储
  • C++存储

方案选择

  • 配置表全部放到C++
  • 生成lua config wrap文件
  • 生成c# config wrap文件
  • 弱表
  • 支持强引用
  • C++内存压缩

优势

  • C#/lua访问C++非常高效
  • 全局只有一份,配置数据零余
  • 内存占用更低
  • 代码结构更优

C++内存压缩

压缩方法

  • 对象池,合并重复单元格
  • 位运算,优化列数据量
  • int8替代指针引用
  • mmap文件映射
  • 数据结构优化
  • 延迟加载
  • ...

场景流式加载

背景

  • 1024*1024
  • 同屏200W面
  • 贴图1024
  • 自由视角

美术资产分类

  • 微景,装饰物,不影响游戏内容,比如碰撞,导航
  • 近景,小型建筑物
  • 中景,房屋建筑
  • 远景,地形,轮廓,特色标志性建筑

加载策略

  • 格子加载
  • 分层加载
  • 连通图加载
  • 自适应加载
  • 全局LOD加载

总结

  • 精准定位,杜绝主观猜测
  • 深入分析,精通业务
  • 全量优化,不放过任何一个模块
  • 逐个攻克,没有捷径
相关推荐
ZXH01222 小时前
性能提升60%:性能优化指南
前端·性能优化
煮粥侠_993 小时前
做RPG游戏时在对话的excel配置表中使用富文本
游戏·unity
by__csdn3 小时前
javascript 性能优化实战:异步和延迟加载
开发语言·前端·javascript·vue.js·性能优化·typescript·ecmascript
by__csdn3 小时前
JavaScript性能优化实战:减少DOM操作全方位攻略
前端·javascript·vue.js·react.js·性能优化·typescript
灰灰勇闯IT3 小时前
RN性能优化实战:从卡顿到丝滑的进阶之路
学习·性能优化
_Cherry|16 小时前
Unity按钮动态效果
unity·游戏引擎
元境16 小时前
“3D数字内容创新发展高峰论坛”在京成功举办,多项重要合作与课题启动
3d
song50117 小时前
鸿蒙 Flutter 图像识别进阶:物体分类与花卉识别(含离线模型)
人工智能·分布式·python·flutter·3d·华为·分类
_Cherry|17 小时前
Unity读取文件夹内容
unity·c#