实际项目中发现的许多问题都是源自无心之过:临时的“测试”更改和疲惫不堪的开发人员的误点击可能会暗地里添加性能不良的资源或更改现有资源的导入设置。

对于任何大规模的项目,最好是将防止人为错误作为第一道防线。编写一小段代码来禁止将 4K 未压缩纹理添加到项目中,是相对简单的事情。

但是,这种错误操作却是十分常见的。一个 4K 的未压缩纹理会占用 60 MB 的内存。在低端移动设备(如 iPhone 4S)上,占用的内存超过大约 180–200 MB 是十分危险的。如果误添加此类纹理,就会无意中占用应用程序内存预算的三分之一到四分之一,并导致难以诊断的内存不足错误。

虽然现在可以使用 5.3 版内存性能分析器来跟踪这些问题,但最好在最初就确保这些错误不可能发生。

使用 AssetPostprocessor

Unity Editor 中的 AssetPostprocessor 类可用于在 Unity 项目上强制执行某些最低标准。导入资源时将回调此类。要使用此类,应继承 AssetPostprocessor 并实现一个或多个 OnPreprocess 方法。重要的方法包括:

  • OnPreprocessTexture

  • OnPreprocessModel

  • OnPreprocessAnimation

  • OnPreprocessAudio

请参阅 AssetPostprocessor 的脚本参考,了解更多可能的 OnPreprocess 方法。

public class ReadOnlyModelPostprocessor : AssetPostprocessor {

   public void OnPreprocessModel() {

        ModelImporter modelImporter =

 (ModelImporter)assetImporter;

        if(modelImporter.isReadable) {

            modelImporter.isReadable = false;

            modelImporter.SaveAndReimport();

        }

    }

} 

这是一个在项目中 AssetPostprocessor 强制执行规则的简单示例:

每次将模型导入项目时,或者模型的导入设置发生更改时,都会调用此类。该代码只是检查 Read/Write enabled 标志(由 isReadable 属性表示)是否设置为 true。如果是,则强制将标志位更改为 false,然后保存并重新导入资源。

请注意,调用 SaveAndReimport 会导致再次调用此代码片段!但是,因为现在已确保 isReadable 为 false,所以此代码不会产生无限的重新导入循环。

此变更的原因将在下面的“模型”部分讨论。

通用资源规则

纹理

禁用 read/write enabled 标志

Read/Write enabled 标志使纹理在内存中保留两次:一次保存在 GPU 中,一次保存在 CPU 可寻址内存中(1)(注意: 这是因为大多数平台上从 GPU 内存回读的速度极慢。将纹理从 GPU 内存读入临时缓冲区以供 CPU 代码(例如 Texture.GetPixel)使用将是非常低效的)。在 Unity 中,默认情况下禁用此设置,但可能会无意中将其打开。

只有在着色器之外操作纹理数据时(例如使用 Texture.GetPixel 和 Texture.SetPixel API 时)才需要 Read/Write Enabled,否则应尽可能避免使用它。

尽可能禁用 Mipmap

如果对象相对于摄像机具有相对不变的 Z 深度,则可禁用 Mipmap,这样将大约节省加载纹理所需的内存的三分之一。如果对象的 Z 深度会发生变更,则禁用 Mipmap 可能导致 GPU 上的纹理采样性能变差。

通常情况下,这对于 UI 纹理以及在屏幕上以恒定大小显示的其他纹理非常有用。

压缩所有纹理

使用适合项目目标平台的纹理压缩格式对于节省内存至关重要。

如果所选的纹理压缩格式不适合目标平台,Unity 会在加载纹理时解压缩纹理,这将消耗 CPU 时间和额外的内存。此问题在 Android 设备上最常见,因为此类平台通常因芯片组不同而支持截然不同的纹理压缩格式。

实施合理的纹理大小限制

虽然很简单,但也很容易忘记调整纹理大小或无意中更改纹理大小导入设置。应确定不同类型纹理的合理最大值,并通过代码强制执行这些限制规则。

对于许多移动应用程序,2048x2048 或 1024x1024 足以满足纹理图集的要求,而 512x512 足以满足应用于 3D 模型的纹理的要求。

模型

禁用 Read/Write enabled 标志

模型的 Read/Write enabled 标志与纹理的上述相应标志具有相同的工作原理。但是,模型在默认情况下会启用该标志。

如果项目在运行时通过脚本修改网格 (Mesh),或者如果网格用作 MeshCollider 组件的基础,则 Unity 会要求启用此标志。如果模型未在 MeshCollider 中使用并且未被脚本操纵,请禁用此标志以节省一半模型内存。

在非角色模型上禁用骨架

默认情况下,Unity 会为非角色模型导入通用骨架。如果模型在运行时实例化,则会导致添加 Animator 组件。如果模型没有通过动画系统进行动画处理,则会给动画系统增加不必要的开销,因为每帧都必须运行一次所有激活的 Animator。

在非动画模型上禁用骨架可以避免自动添加 Animator 组件,并防止可能无意中向场景添加不需要的 Animator。

在动画模型上启用 Optimize Game Objects 选项

Optimize Game Objects 选项对动画模型有着显著的性能影响。禁用该选项后,Unity 会在每次实例化模型时创建一个大型变换层级视图来镜像模型的骨骼结构。此变换层级视图的更新成本很高,尤其是在附加了其他组件(如粒子系统或碰撞体)的情况下。它还限制了 Unity 通过多线程执行网格蒙皮和骨骼动画计算的能力。

如果需要暴露模型骨骼结构上的特定位置(例如暴露模型的双手以便动态附加武器模型),则可在 Extra Transforms 列表中将这些位置专门设为允许状态。

如需了解更多详细信息,请参阅 Unity 手册的 Model Importer 页面。

尽可能使用网格压缩

启用网格压缩可减少用于表示模型数据不同通道的浮点数的位数。这样做可能导致精确度的轻微损失,在用于最终项目之前,美术师应评估这种不精确性的影响。

在给定压缩级别中使用的具体位数在 ModelImporterMeshCompression 脚本参考中有详细说明。

请注意,可对不同的通道使用不同级别的压缩,因此项目可选择仅压缩切线和法线,同时保持 UV 和顶点位置不压缩。

注意网格渲染器设置

将网格渲染器添加到预制件或游戏对象时,请注意组件上的设置。默认情况下,Unity 会启用阴影投射和接收、光照探针采样、反射探针采样和运动矢量计算。

如果项目不需要这些功能中的一个或多个,请确保通过自动脚本关闭它们。添加网格渲染器的任何运行时代码也都需要处理这些设置。

对于 2D 游戏,在启用阴影选项的情况下意外地将网格渲染器添加到场景会为渲染循环添加完整的阴影 pass。通常情况下,这是对性能的浪费。

音频

适合平台的压缩设置

应为音频启用与可用硬件匹配的压缩格式。所有 iOS 设备都包含硬件 MP3 解压器,而许多 Android 设备本身支持 Vorbis。

此外,应将未压缩的音频文件导入 Unity。Unity 在构建项目时总是会重新压缩音频。无需导入压缩的音频再重新压缩,这只会降低最终音频剪辑的质量。

将音频剪辑强制设置为单声道

很少有移动设备实际配备立体声扬声器。在移动平台项目中,将导入的音频剪辑强制设置为单声道会使其内存消耗减半。此设置也适用于没有立体声效果的任何音频,例如大多数 UI 声音效果。

降低音频比特率

尽量降低音频文件的比特率,以进一步节省内存消耗和构建的项目大小,但这种情况需要咨询音频设计师。

Unity性能优化——资源优化(一)的更多相关文章

  1. Unity性能优化(3)-官方教程Optimizing garbage collection in Unity games翻译

    本文是Unity官方教程,性能优化系列的第三篇<Optimizing garbage collection in Unity games>的翻译. 相关文章: Unity性能优化(1)-官 ...

  2. Unity性能优化(4)-官方教程Optimizing graphics rendering in Unity games翻译

    本文是Unity官方教程,性能优化系列的第四篇<Optimizing graphics rendering in Unity games>的翻译. 相关文章: Unity性能优化(1)-官 ...

  3. Unity性能优化(2)-官方教程Diagnosing performance problems using the Profiler window翻译

    本文是Unity官方教程,性能优化系列的第二篇<Diagnosing performance problems using the Profiler window>的简单翻译. 相关文章: ...

  4. Unity性能优化专题---腾讯牛人分享经验

    这里从三个纬度来分享下内存的优化经验:代码层面.贴图层面.框架设计层面. 一.代码层面. 1.foreach. Mono下的foreach使用需谨慎.频繁调用容易触及堆上限,导致GC过早触发,出现卡顿 ...

  5. Unity 性能优化(力荐)

    开始之前先分享几款性能优化的插件: 1.SimpleLOD : 除了同样拥有Mesh Baker所具有的Mesh合并.Atlas烘焙等功能,它还能提供Mesh的简化,并对动态蒙皮网格进行了很好的支持. ...

  6. Unity性能优化(1)-官方教程The Profiler window翻译

    本文是Unity官方教程,性能优化系列的第一篇<The Profiler window>的简单翻译. 相关文章: Unity性能优化(1)-官方教程The Profiler window翻 ...

  7. spark性能调优:资源优化

    在开发完Spark作业之后,就该为作业配置合适的资源了.Spark的资源参数,基本都可以在spark-submit命令中作为参数设置.很多Spark初学者,通常不知道该设置哪些必要的参数,以及如何设置 ...

  8. 【原创】构建高性能ASP.NET站点 第七章 如何解决内存的问题(前中篇)—托管资源优化—监测CLR性能

    原文:[原创]构建高性能ASP.NET站点 第七章 如何解决内存的问题(前中篇)-托管资源优化-监测CLR性能 构建高性能ASP.NET站点 第七章 如何解决内存的问题(前中篇)—托管资源优化—监测C ...

  9. Unity骨骼动画资源解析与优化

    一,背景 最近发现项目的动画文件有点大,不光内存大,而且文件也很大,所以从这2个方面下手处理 二,动画文件大小优化 为了优化动画文件大小,我们可以先分析下文件,Ctrl+D将动画文件从FBX拷贝出来, ...

  10. Unity优化方向——优化Unity游戏中的脚本(译)

    原文地址:https://unity3d.com/cn/learn/tutorials/topics/performance-optimization/optimizing-scripts-unity ...

随机推荐

  1. Java实现书城项目(增删)

    书城项目 登录 dao 接口:UserDao Users login(String username,String password); 实现:UserDaoImpl QueryRunner quer ...

  2. 基于 Mindspore 框架与 ModelArts 平台的 MNIST 手写体识别实验

    简介 实验包含 2部分: 基于 Mindspore 框架的模型本地训练及预测 基于 Modelarts 平台和 PyTorch框架的模型训练及部署 基于 Mindspore 框架的模型本地训练及预测 ...

  3. evalFn 字符串转执行函数 附带JSONParse函数

    const evalFn = (fn) => { var Fun = Function // 一个变量指向Function,防止前端编译工具报错 return new Fun('return ' ...

  4. PAT 甲级1008【1008 Elevator】

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import ...

  5. [STM32 HAL]一种可能不错的DMA处理串口数据方案

    [STM32 HAL]一种可能不错的DMA处理数据方案 原文链接:https://blog.csdn.net/youmeichifan/article/details/51750435?spm=100 ...

  6. LiveData详细分析

    目录介绍 01.LiveData是什么东西 02.使用LiveData的优势 03.使用LiveData的步骤 04.简单使用LiveData 05.observe()和observerForever ...

  7. 重返ubuntu世界

    一直对"重返"两个字充满了情怀感,因为会想起小时候看的一本龙珠同人的标题,它就唤作<重回龙珠世界>.最近这五年基本都是在MacOS下工作和学习的,也习惯用MacOS.就 ...

  8. KingbaseES V8R6 集群运维系列 -- 命令行部署repmgr管理集群+switchover测试

    本次部署未使用securecmd/kbha工具,无需普通用户到root用户的互信. 一.环境准备 1.创建OS用户 建立系统数据库安装用户组及用户,在所有的节点执行. root用户登陆服务器,创建用户 ...

  9. UE4中的C++编程简介

    对官方文档的学习链接 利用UE创建一个C++基类 在编辑器中可以选择父类,根据这个父类我们可以创建一个基类用于后续的蓝图类制作. 以Actor父类为例创建基类,其头文件会包含一个构造函数,一个Tick ...

  10. 谈谈MyBatis持久层框架

    谈谈 MyBatis 源自官方文档:MyBatis 是一款优秀的持久层框架,它支持自定义 SQL.存储过程以及高级映射.MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作. ...