zoukankan      html  css  js  c++  java
  • unity3d代码优化标准

    转载自:https://blog.csdn.net/m0_37283423/article/details/84378384

    代码优化

           ● 尽可能使用for来代替foreach:每次foreach会产生一个Enumerator,迭代器会额外分配内存。

           ● 尽量避免使用Lambda表达式:存在内存泄露隐患。

           ● 尽量避免使用LINQ:部分功能无法在某些平台上使用,且会分配大量GC Alloc。

    ​       ● 控制StartCorountine()的次数:开启一个协程,至少分配37B的内存(Coroutine类的实例 - 21B;Enumerator - 16B)。

           ●​ 使用StringBuilder来代替String进行字符串拼接:StringBuilder.Append方法在拼接字符串时,变化总是发生在同一个内存块中;而String + String + ...这种字符串拼接方式,会频繁申请内存并释放,导致GC频繁调用。

           ● 缓存组件:每次GetComponent均会分配一定的GC Alloc;每次获取对象名称Object.name(实际为Object.get_name())会分配39B(具体大小视实际情况而定)的堆内存。

           ●​ 避免使用开销大的函数:如GameObject.Find、GameObject.FindWithTag、Object.FindObjectOfType等查询方法。

           ● 使用GameObject.CompareTag代替GameObject.tag:GameObject.tag会在内部循环调用对象分配的标签属性并分配额外的内存。

           ● 使用ObjectPool对象池来管理对象:避免频繁的Instance和Destroy,这两个操作都挺耗性能的。

           ● 尽量不要在Update()函数中做复杂计算:如若需要,可以隔N帧计算一次。

           ●​ 尽量减少函数调用栈:如用x = (x > 0 ? x : -x)代替x = Mathf.Abs(x)。

    纹理优化

           ● 纹理压缩格式:iOS使用PVRTC格式;Android使用ETC格式;Windows使用DXT格式。

           ● 凡是3D场景,都应该尽可能启用MipMaps。如果硬件MipMaps无法满足效果要求:1、使用自己生成的Mipmaps;2、使用Aniso。

           ● 如果纹理用于UI或2D场景,禁用MipMaps。

           ● 通过减色的方式降低纹理大小。

    ​内存优化

           ● 建议总内存控制在150MB以下;堆内存控制在40MB以下。

           ● 切换场景时避开内存峰值。当前一个场景还未释放就切换到新场景,这时由于两个场景的内存叠加容易造成内存峰值。可以采用在屏幕中间遮盖一个Loading场景,在旧场景释放完成,并且新场景初始化结束后,再隐藏Loading场景。

           ●​ 使用Prefabs(凡是场景物体,都应该制作成Prefabs)。

           ● 通过ObjectPool对象池来避免内存的频繁操作,从而避免内存碎片影响到大内存块的申请;尝试在切换场景时不释放公共UI资源。

           ●​ 通过LoadManager,保证在同一时间段内仅载入一个WWW对象,实现顺序加载。

           ●​ 纹理内存占用过大:峰值 < 50MB。

           ●​ 内存泄露:内存需保持升降一致,避免泄露。

           ●​ 网格资源内存过大:峰值 < 20MB。

           ●​ 动画片段:内存 < 15MB,警惕资源泄露。

           ●​ 音频资源:内存 < 15MB,警惕资源泄露。​

    渲染优化

           ●​ DrawCall数量:峰值 < 250,主体范围(5% - 95%)应在(0 - 200)个之内。

           ● Triangle数量:峰值 < 100000/帧。

           ● VBO上传量:峰值 < 5MB,频繁加载的资源使用缓存池缓存。

           ●​ Skinned Mesh数量:峰值 < 50,对应Profiler中的MeshSdinning.Update、Animator.Update。

    ​       ● RenderTexture:数量 < 10。

    CPU优化​

           ●​ Rigidbody数量:峰值 < 50/帧,对应Profiler中的Physics.Simulate。

           ● 碰撞体数量:峰值 < 100/帧,对应Profiler中的Physics.Simulate。

    合理使用AssetBundles

    ● 采用依赖性打包

        ●​ Assetdatabase.GetDependencies

        ●​ Push / Pop

    ● WWW vs. CreateFromFile

        ● WWW常被用于加载采用Unity标准压缩方法压缩过的AssetBundles。

        ●​  CreateFromFile只能加载非压缩格式的本地AssetBundles;可以先采用其他压缩格式进行压缩,下载到本地后自行解压,再行加载和使用。

    ● AssetBundle.mainAsset的功能往往被忽视

        ● 它可以是标准的资源asset,用来存储AssetBundles中最重要的资源文件。

        ●  也可以是TextAsset,其中可以包含任意内容,推荐用来记录每个AssetBundle中的物体列表和信息描述。

    Build AssetBundles

    ● 问题:当修改AssetBundles中的内容时,需要重新Build这些AssetBundles才能使其生效。这个过程往往非常耗时并影响开发效率。

    ● 开发阶段和发布阶段使用不同的策略:

        ●​ 为了提高在Unity Editor中反复修改AssetBundles的调试效率,推荐开发时使用Resources.LoadAssetAtPath来避免重新建立AssetBundles。

        ●​ 在发布时才使用唯一的脚本打包AssetBundles。

    LoadAssetFromAssetBundle

    AssetDatabase.ImportAsset

    ● AssetDatabase.ImportAsset有三个重要事实:

        ●​ 它是将一个外部asset转化为Unity内部能够识别的internal asset,但并不实际在内存中加载asset,更没有返回值。

        ● 它会根据AssetImporter中的相关设定对asset的相关属性进行修改,尽管两个API之间没有任何的参数传递。

        ● 它常常被用于在调用BuildPipeline.BuildAssetBundle前强行重新导入一个asset。

        ●​ 几种常用的AssetImporter类型:TextureImporter、ModelImporter及MovieImporter。

    预处理和后处理函数

    ● AssetPostprocessor的作用

        ●​ AssetPostprocessor可以在import每个asset之前和之后分别自动触发AssetPostprocessor.OnPreprocessXXX和AssetPostprocessor.OnPostprocessXXX。

        ●​ 方便用户介入和修改资源导入的过程。

    Build Player

    ●  自动编译Player

        ●​ 支持命令行进行编译。

        ● 编写编译脚本,并放在Assets/Editor目录下。

        ●​ 脚本中声明一个类,包含一个静态方法,通过BuildPipeline.BuildPlayer来实现编译工作。

    ● 编译后处理脚本

        ●​ Unity支持在编译好可执行程序之后,通过后处理脚本对其进行一定的修改,例如制作安装文件等。

            ●​ 在Windows平台下,可以在编辑器脚本(Editor Script)中使用BuildPipeline.BuildPlayer方法来进行编译,并在其后添加任意的后处理代码。

            ●​ 在Mac平台下,Unity在编译工程后会自动查找一个名为PostprocessBuildPlayer的后处理脚本文件,用于实现编译后处理;后处理脚本可以是sh、perl或任意与命令行兼容的语言。

    项目发布策略

    ●  对移动芯片的支持

        ● 从Unity 4.0开始,Unity停止了对ARM V6架构的支持。

        ●​ Unity 3.5.x版本仍旧支持ARM V6架构。

    ● Graphics Emulation

        ●​ 在不使用实际硬件设备的前提下,在Unity编辑器中就可以模拟测试不同图形硬件对当前项目中所使用的图形API的支持能力(对Editor->Graphics Emulation进行设置)。

    ●​ 发布包的代码保护

        ●​ Unity脚本在iOS平台下是安全的,与是否使用AssetBundle无关。

        ●​ 对于Android和其他平台,可以采用AssetBundle + TextAsset的方式进行,也可以采用代码混淆的方式进行。

        ●​ 在所有平台下都可以使用Native DLL。

    ● 发布包的代码加密

        ● 需通过AssetBundle和TextAsset来实现,即把代码编译为TextAsset,并打包入AssetBundle中,参考官方文档:“Including scripts in AssetBundles”一节:http://docs.unity3d.com/Documentation/Manual/scriptsinassetbundles.html

        ● 其中TextAsset并不是真正意义上的Text,而是编译好的dll文件,是以binary形式存在的。参考官方文档“Text Asset”中的“Binary data”一节:http://docs.unity3d.com/Documentation/Components/class-TextAsset.html

    ● 发布包的美术资源加密

        ●​ 对于所有平台,最常见的是对贴图进行加密,通过AssetBundle和TextAsset来实现。

    ● 程序发布后的增量更新

        ●​ 原理:Unity脚本经过编译后就不能再修改,但是可以添加。

        ●​ 方案1:将脚本与资源全部分离。

            ●​ 项目管理非常麻烦。

            ●​ 动态挂载所有脚本。

            ●​ 无法在编辑器中使用动态编辑。

        ● 方案2:将接口与实现分离。

            ●​ 不改变用户工作流程。

            ●​ 仍可在编辑器重使用动态编辑。

            ●​ 对代码起到一定的保护作用(可以混淆)。

            ●​ 对原有的AssetBundles打包方案没有任何影响。

  • 相关阅读:
    Power of Cryptography
    Radar Installation
    Emag eht htiw Em Pleh
    Help Me with the Game
    89. Gray Code
    87. Scramble String
    86. Partition List
    85. Maximal Rectangle
    84. Largest Rectangle in Histogram
    82. Remove Duplicates from Sorted List II
  • 原文地址:https://www.cnblogs.com/mttnor/p/10442837.html
Copyright © 2011-2022 走看看