代码优化:
1.以物体的Transform组件为例,我们应该只访问一次,之后就将它的引用保留,而非每次使用都去访问。这里有人做过一个小实验,就是对比通过 方法GetComponent()获取Transform组件, 通过MonoBehavor的transform属性去取,以及保留引用之后再去访问所需要的时间:
GetComponent = 619ms
Monobehaviour = 60ms
CachedMB = 8ms
Manual Cache = 3ms
2.如上所述,最好不要频繁使用GetComponent,尤其是在循环中。
3.善于使用OnBecameVisible()和OnBecameVisible(),来控制物体的update()函数的执行以减少开销。
4.使用内建的数组,比如用Vector3.zero而不是new Vector(0, 0, 0);
5.对于方法的参数的优化:善于使用ref关键字。值类型的参数,是通过将实参的值复制到形参,来实现按值传递到方法,也就是我们通常说的按值传递。复制嘛,总会让人感觉很笨重。比如Matrix4x4这样比较复杂的值类型,如果直接复制一份新的,反而不如将值类型的引用传递给方法作为参数。
6.字符串连接的处理。因为将两个字符串连接的过程,其实是生成一个新的字符串的过程。而之前的旧的字符串自然而然就成为了垃圾。而作为引用类型的字符串,其空间是在堆上分配的,被弃置的旧的字符串的空间会被GC当做垃圾回收。
7.尽量不要使用foreach,而是使用for。foreach其实会涉及到迭代器的使用,而据传说每一次循环所产生的迭代器会带来24 Bytes的垃圾。那么循环10次就是240Bytes。
8.不要直接访问gameobject的tag属性。比如if (go.tag == “human”)最好换成if (go.CompareTag (“human”))。因为访问物体的tag属性会在堆上额外的分配空间。如果在循环中这么处理,留下的垃圾就可想而知了。
7.使用“池”,以实现空间的重复利用。
9.最好不用LINQ的命令,因为它们会分配临时的空间,同样也是GC收集的目标。而且我很讨厌LINQ的一点就是它有可能在某些情况下无法很好的进 行AOT编译。比如“OrderBy”会生成内部的泛型类“OrderedEnumerable”。这在AOT编译时是无法进行的,因为它只是在 OrderBy的方法中才使用。所以如果你使用了OrderBy,那么在IOS平台上也许会报错。
10.如果没有必要每帧都处理,则可以每隔几帧处理一次
voidUpdate(){if(Time.frameCount%6==0) { DoSomething(); }}
一般不推荐使用 OnBecameVisible()和OnBecameInvisible()方法。
那还有啥可替代的呢?
有!渲染器扩展方法来实现。
添加一个类
public static class RendererExtensions
{
//渲染器扩展方法
public static bool IsVisibleFrom(this Renderer renderer, Camera camera)
{
Plane[] planes = GeometryUtility.CalculateFrustumPlanes(camera);
return GeometryUtility.TestPlanesAABB(planes, renderer.bounds);
}
}
其它类调用,切记该组件必须有个渲染器…
void Update ()
{
if (!renderer.IsVisibleFrom(Camera.main))
{
print(“消失在屏幕内!!!!!!!!!!!!!!!!”);
}
}