1.Avoid retrieving string properties from GameObjects

通常来讲,从C#的object中获取string 属性没有额外的内存开销,但是从Unity中的Gameobject获取string属性不一样,这会产生上一篇讲到的 Native-Managed Bridge(Native内存和托管内存间的传递)

tag和name是GameObject中会产生这种现象的两个属性,我们应该尽量少的在运行时调用这两个属性,比如用在Editor编程中更合适。但是Tag这个东西太常用也非常有用,在运行时经常会用到,这会经常带来麻烦,举个栗子,下边的代码在每次迭代中都会产生额外的内存开销:

for (int i = 0; i < listOfObjects.Count; ++i)
{  if (listOfObjects[i].tag == "Player") {    // do something with this object  }
} 

还好Unity提供了 CompareTag()这个方法来用来tag间的比较,这个方法避免了Native-Managed Bridg(不知道咋避免的,没有讲原理)

来,让我们测试下:

通过键盘我们可以控制使用哪个函数,来瞅瞅结果:

分别运行1000万次,可以看到使用.tag方法时会有很多内存分配,如果分配过多会进而产生GC。并且.tag方法运行大概消耗2000毫秒,而ComparTag方法大概消耗1000毫秒,速度也慢于CompareTag方法。所以结论就是不要使用.tag方法。

很不幸的是Unity对于name属性没有提供不消耗内存的方法,所以有的时候需要调用name属性去判断时,不如考虑考虑用tag来代替。值得一提的是ComparTag方法调用时传入的字符串,比如"Player"并不会产生额外的内存开销,因为在初始化时已经分配好这些硬编码的字符串,这里这是运行时的引用。

2. Use appropriate data structures

C#在System.Collection中提供了很多不同的数据结构,最常用的俩个就是List<T>和Dictionary<K, V>。

如果我们想要做的是遍历数据集,那List更合适一些,因为List在内存中的分布式连续的,因此遍历会更准确更快的命中内存位置。

Dictionary最合适的情况是两个objects相互关联,我们更多的是用来查询,插入,删除等操作。

如果既想要遍历速度快,又想增删改查快,不好意思,没有这种美事儿,目前没有这种数据结构,书作者的建议是。。。如果有这种硬性需求,那就两个一起用,一个list一个dict,比如一个playerList 一个 playerDict

3.Avoid re-parenting Transforms at runtime

在Unity的早期版本中(5.3更早之前)Transform的引用在内存中的排布和Dict很像,也是随机排布。但是新版本后,Unity对于在同一个parent下的所有Transforms,内存排布变成了连续的类似动态数组,这会给例如物理系统和动画系统等许多系统带来非常大的性能提升,因为这加快了Transform的遍历。万事肯定不是完美的,想获得速度的提升,就会有所牺牲。当我们想给一个GameObject 换个爹(parent)时,新的爹(parent)必须从自己已预先分配好的内存空间中分出一部分给这个新移过来的Transform并且重新根据depth排序,如果这个新爹(parent)没有足够的空间去适应新来的儿子(child),那它只好扩展自己的内存buffer,这有可能会消耗不好少时间。

当我们 instantiate 一个新的GameObject时,要处理的一件事就是给这个GameObject认个爹,如果不处理的话默认是null,也就是孤儿,会直接在Hierarchy的root下存放。Hierarchy 根目录下的所有Transform都需要分配一段内存buffer去存储自己现有的儿子们以及未来还可能新有的,但是如果当我们Instantiate后立刻给一个GameObject认个爹,就可以避免分配这部分内存buffer!因此我们可以 在调用GameObject.Instantiate()时传入parent的Transform而避免分配内存这步。

另一种方法是在我们需要之前就给root Transform提前分配更大的内存buffer,从而避免在同一帧里既需要重新给GameObject认爹还需要扩展内存Buffer,这个操作可以通过修改Transform的hierarchyCapacity属性达到,如果我们可以提前就预估好有多少个儿子,那就可以节省很多的内存分配操作。

4.Consider caching Transform changes

Transform脚本存储了它相对于其parent的数据,这意味着如果获取和修改一个Transform脚本的position,rotation或者scale属性,都将引起许多额外的矩阵运算(类似坐标空间变换)。这个object在Hierarchy Window中所处层级越深,那就需要计算的越多。

然而这也意味着如果使用localPosion,localRotation和localScale不会有这部分开销,因为这些值已经是直接存储在了Transform上,可以直接获得,因此能用local属性的时候就尽可能的使用local。

不幸的是世界坐标和本地坐标的变换在很多时候会简化和解决3D的一些问题,因此有时候也有必要牺牲一些小性能来解决复杂的3d数学运算问题。

另外一个要注意的就是要尽量避免不断的对Transform脚本的属性进行更改,因为每次更改都会调用Unity内部的消息机制,Unity需要把更改的消息发送给例如Collider,Rigidbody,Light,Camera等等以保证物理和渲染系统能知道新的Transform属性从而进行对应的更新。

我们会经常看到在同一帧中对Transform的属性进行了多次的修改,这每次修改都会带来内部消息的传递,即使是在同一帧里。因此,我们应该尽可能减少修改次数,比如先用变量缓存,在帧的最后再调用,比如下边这个例子:

Unity 2017 Game Optimization 读书笔记(3)Scripting Strategies Part 3相关推荐

  1. Unity 2017 Game Optimization 读书笔记(1)Scripting Strategies Part 1

    1.Obtain Components using the fastest method Unity有多种Getcomponet的方法: GetComponent(string), GetCompon ...

  2. Unity 2017 Game Optimization 读书笔记 Scripting Strategies Part 5

    一. Disable unused scripts and objects 场景中激活的物体或者脚本越多,开销越大.对于很多并没有产生作用的脚本和物体,可以隐藏掉从而提升性能,比如FPS游戏中视野外的 ...

  3. Unity 2017 Game Optimization 读书笔记(4)Scripting Strategies Part 4

    1.Avoid Find() and SendMessage() at runtime SendMessage() 方法和 GameObject.Find() 相关的一系列方法都是开销非常大的.Sen ...

  4. Unity 2017 Game Optimization 读书笔记(2)Scripting Strategies Part 2

    1. Share calculation output 和上一个Tip很像,可以缓存计算结果或者各种信息,避免多次重复的计算,例如在场景里查找一个物体,从文件读取数据,解析Json等等. 容易忽略的点 ...

  5. Unity 2017 Game Optimization 读书笔记 Dynamic Graphics (6)

    1. Use less texture data 这条优化技巧非常直接,减少texture的数据量,减少分辨率或者降低位数,虽然可能会降低渲染质量.但是通常使用16-bit textures并不会明显 ...

  6. Unity 2017 Game Optimization 读书笔记 Dynamic Graphics (5) Shader优化

    Shader optimization Fill Rate和 Memory Bandwidth开销最大的地方就是Fragment Shader.开销多大取决于Fragment Shader的复杂程度: ...

  7. Unity 2017 Game Optimization 读书笔记 Dynamic Graphics (4)

    Optimizing Unity UI 本章讲探讨一些能够提升UGUI性能的优化方法. 1.Use more Canvases 一个Canvas的主要任务就是管理它层级下的所有UI元素,并且通过Dra ...

  8. Unity 2017 Game Optimization 读书笔记 Dynamic Graphics (3)

    Rendering performance enhancements Enable/Disable GPU Skinning 开启GPU Skinning可以减轻CPU或GPU中Front End部分 ...

  9. Unity 2017 Game Optimization 读书笔记 The Benefits of Batching

    batching(合批) 和大量的描述一个3D物体的数据有关系,比如meshes,verices,edges,UV coordinates 以及其他不同类型的数据.在Unity中谈论batching, ...

最新文章

  1. C# 获取图片的EXIF 信息
  2. 业余实现一个统计A股数据工具
  3. WPF-常用布局容器
  4. criterion java_Java Criterion類代碼示例
  5. linux命令之查看当前shell环境变量-env
  6. MXD文档保存和地图浏览
  7. kafka 启动_深入理解Kafka服务端之Acceptor线程是如何启动和工作的
  8. VTK:导出PolyData场景用法实战
  9. php控制器是啥,控制器的定义
  10. AS安装APK失败的两种情况
  11. catboost进行分类并开启GPU模式
  12. mysql5.7修改root密码_七小服公开课EMC isilon修改丢失的root密码
  13. 学c语言做练习之文件
  14. 如何制作频数折线图(详细)
  15. Excel自定义下拉框
  16. 高速下载文件的方法(对百度,城通等网盘无效)
  17. java tbase_TBase备份恢复实验
  18. uniapp本机号码一键登录
  19. 从融360到理财魔方、再到韭菜财经,新金融正确姿势为哪般?
  20. WinRAR 实现简单的自解压

热门文章

  1. mysql外表内表_mysql 子查询 将最外表带入子查询内2层 的另一种解决方法
  2. centos6 进入命令行_CentOS 6.x误删libc.so.6,紧急恢复
  3. 升级鸿蒙系统照片,华为鸿蒙系统照片出炉,神似EMUI,海内外花粉沸腾了
  4. oracle 表空间写文件,Oracle表空间和数据文件管理
  5. jquery多维对象计算个数_多维尺度分析理论概述
  6. python相关工作岗位_西安掌握Python有哪些工作岗位能够选择
  7. Linux软件包管理的知识点,Linux基础知识之软件包管理(二)
  8. 图论--LCA--树上倍增法(在线)
  9. 如何在virtualbox中对虚拟机截图
  10. [机器学习]gcForest算法理解