1.Unity中影响性能的几个因素(游戏优化)

计算机资源有两种:CPU负责其中的帧率,GPU主要负责分辨率

对于CPU:

渲染方面

1. 过多地调用Draw Calls命令,每次调用都要预先计算好顶点数据(位置、法线、颜色、纹理坐标等),导致CPU过载。

优化方案:

1. 顶点优化:

a. LOD(level of detail)技术:根据摄像机距离对象的远近,选择使用不同精度的模型。

b.使用遮挡剔除(Occlusion culling)技术。

c. 使用视锥剔除技术。

2. CPU优化:

a. 批处理,同时处理统一材质的物体。

2. 复杂的资源,例如不合理的网格资源和纹理资源等。

优化方案

1. 贴图的大小非2的次方时,最好改成2的次方,或者合并其他贴图使其尽量为2的次方。

2. 采用享元模式,减少多个重复资源的内存占用。

3.采用原型模式,降低复杂对象生成过程,提高运行效率。

UI模块:UI性能低效。

优化方案

1. 降低频繁更新UI元素的频率:例如怪物血量控制在某个区域才更新,或者技能CD,伤害飘字隔帧跟新,基于事件通知更新UI。

2. 复杂的UI(字体加了阴影、描边等)不要变动,或者少用

3. UI出现重叠时,关闭被遮挡的UI

加载模块:场景的卸载和加载(资源加载和实例化)。

优化方案

1. 同步的方式显示进度条加载,后面采用异步的方式加载资源。

代码效率: “二八原则”:80%的性能开销都集中在20%的函数上

其他:

1. ARPG游戏中的动画系统和物理系统。

2. 音乐休闲类游戏中的音频系统和粒子系统等。

优化方案

1. 采用享元模式,减少多个重复资源的内存占用。

对于内存:

资源内存占用(资源的内存占用往往占据了总体内存的70%以上):

纹理(Texture)、网格(Mesh)、动画片段(AnimationClip)、音频片段(AudioClip)、材质(Material)、着色器(Shader)、字体资源(Font)以及文本资源(Text Asset)等等。其中,纹理、网格、动画片段和音频片段则是最容易造成较大内存开销的资源。

1. 纹理:纹理格式、纹理尺寸、Mipmap功能、read&write。

2. 网格:Normal、Color、Tangent。

3. 引擎自身模块占用

4. 托管堆内存占用

优化方案

1.采用对象池优化方案,降低对象的生成和销毁。

2. 享元模式,共用同一份资源。

3. 对象池管理模式,降低资源重复创建和销毁。

4. 合并纹理。

5. 降低纹理大小。

2.对象池的介绍与使用(设计模式)

对象池:一定数量的已经创建好的对象(Object)的集合。当需要创建对象时,先在池子中获取,如果池子中没有符合条件的对象,再进行创建新对象,同样,当对象需要销毁时,不做真正的销毁,而是将其setActive(false),并存入池子中。这样就避免了大量对象的创建。

作用:减少频繁创建和销毁对象带来的成本实现对象的缓存和复用

优点:

1. 提升获取对象的响应速度

2.一定程度上减少了GC的压力

缺点:

1. 出现脏对象:脏对象持有上次使用的引用,导致内存泄漏,脏对象拥有上次的数据,再次调用影响此次程序数据处理

2. 维持大量的对象,占用空间大

3.享元模式(设计模式)

享元模式:不同的实例共享相同的特性(共性),同时保留自己的特性部分,以达到极大减小开销的效果。

优点

1. 传递信息享元化,节约计算时间。

2. 存储信息享元化,节约占用空间。

3. 与对象池联动,进一步减少内存开销。

4. 原型模式(设计模式)

原型模式:将一个或多个对象当做原型,通过统一的生成器克隆出很多类似原型的对象,同时可以通过配置表更改克隆体属性,制造出很多具有自身个性的对象。

优点

1. 创建新的对象比较复杂时,利用原型模式简化对象生成,提供运行效率。

2. 无需初始化对象,动态获取对象运行状态。

缺点

1. 原型对象发生改变,克隆对象也会随之改变。

5. 渲染管线

渲染管线贴切的翻译应该叫渲染流水线,作用:将数据从3D场景转换为2D图像,并最终在屏幕上显示出来的过程。分为:应用阶段、几何阶段、光栅阶段。

应用阶段:碰撞检测、计算数据(顶点坐标法向量纹理坐标纹理),通过数据总线传给图形硬件。

几何阶段:顶点着色器(MVP变换)–》曲面细分着色器(修改网格精度)–》几何着色器(生成多种图元)–》裁剪与背面剔除(去掉多余的点和面)–》屏幕影射(NDC空间)。

光栅阶段:矢量图形转化成像素点的过程 。

6. 项目介绍

雷霆战机:躲避弹幕,击败敌机,通过吃比自己小的敌机升级。

遇到的困难:

1. 飞机机体与子弹不匹配,通过字典匹配在一起。

2. 飞机升级,子弹位置不确定,提取建好空对象,获取空对象位置。

3. 子弹数目过多,导致卡顿,采用对象池统一管理子弹,多个子弹享元同一个贴图(享元模式),多个子弹克隆同一个原型子弹(原型模式)。

4. 敌机生成数量不稳定,种类不均衡,采用工厂模式统一管理,控制各种类敌机数量。

5. UI血量变化,一开始直接将血量写在了UI里,这样不符合低耦合的游戏思想,我又将血量放在飞机类,采用事件的形式,将扣血的通知传递给UI,更新血量。

6. 地图循环播放,无限复制地图实现,发现这样低效,浪费内存,利用offset位置偏移,只用两种地图贴图不停循环实现,或者使用shader方式实现。

7. 音频管理,不同敌机都会有一个音频组件,但不利于统一管理,单例一个总音频统一管理(单例模式)。

学习反馈:学会了如何优化游戏,各种设计模式的使用。