没什么讲的,就几个小点。
1.移出空的回调
类似Awake Start 等Mono继承的类中的回调函数。在场景第一次实例化时,Unity会将任何定义好的回调添加到一个函数指针列表中,然后在指定时刻调用这个列表。即使函数体是空的。
2. Update、Coroutines和InvokeRepeating
协程可以控制回调频率,比Update更自由,通常用于编写短事件序列的脚本。 线程以并发方式在完全不同的CPU内核上运行,多个线程何以同时运行。相反, 协程以顺序的方式在主线程上运行,保证在任何给定时刻都只处理一个协程。 协程缺点: 1. 是普通函数开销的三倍,在gameobject变成不活动时自动停止,且不会重新启动。 2. 很难调试,因为不遵循正常的执行流程;在调用栈上没有调用者。
InvokeRepeating InvokeRepeating和协程最重要的区别是InvokeRepeating完全独立于mono和GameObject的状态。
3.更快的GameObject空引用检查
与典型的C#对象相比,GameObject和MonoBehaviour是特殊对象,因为它们在内存中有两个表示:一个表示存在于管理C#代码的相同系统管理内存中,C#代码是用户编写的(托管代码),而另一个表示存在于另一个单独处理的内存空间中(本机代码)。数据可以在这两者内存空间中移动,带每次都会导致额外的CPU和内存开销。 这种效果叫做跨越本机-托管的桥接。会为对象的数据产生额外的内存分配,以便于垮桥复制,导致GC。
if (!System.Object.ReferenceEquals(gameObject, null)) {// do something}
4.避免从GameObjects检索字符串属性
5.合适的数据结构
如果希望遍历一组对象,最好使用列表List,因为它实际上是个动态数组,对象/引用在内存中彼此相邻,因此迭代导致的缓存丢失最少。 如果两个对象相互关联,且希望快速获取插入删除这些关联,使用字典Dictionary 然而,需要同时处理两种情况:快速找出那个对象映射到另一个对象,同时还能遍历组。最好在列表和字典中存储数据,虽然需要额外的内存,维护多个数据结构。但迭代列表的好处和迭代字典形成鲜明对比。
6.避免修改Transform的父节点
自从5.4后,Transform的内存布局 父-子关系更像动态数组,Unity将所有共享相同父元素的Transform按照顺序存储在预先分配的内存缓冲区中,并根据Hierarchy窗口中父元素的深度进行排序。这种数据结构特点: 优点:进行更快的迭代,对物理和动画有利。 缺点:如果重新指定另一个父元素,需要将新对象放入预先分配的缓存区中,并重新排序。