您的位置:首页 > 移动开发 > Unity3D

一些Unity的使用和优化心得

2013-08-21 09:13 357 查看
下面由一个基础的问题引出全文(题目与解答由Jare师父提供):

有两段代码,循环执行两个比较耗时的方法,假设语言和编译器相同,哪一段会比较快?

for (int i = 0; i < 100; i++)

{

    DoSomethingA();

    DoSomethingB();

}



for (int i = 0; i < 100; i++)

    DoSomethingA();

for (int i = 0; i < 100; i++)

    DoSomethingB();

  

相信有很多人一样,第一眼看起来认为第一段更快点。但实际上答案是第二段快。原因如下:

在这里性能的瓶颈不是循环本身。而是里面的方法。

如果重复执行一个方法,那么CPU的寄存器、一级、二级缓存都很容易命中,比起到内存拿数据快多了。

如果执行完一个执行另一个,那么缓存很可能就被替换掉了,只能到内存拿,甚至内存不够,要到硬盘上的虚拟内存拿。

  

缓存组件查找(以下内容摘自网络)

这种优化需要一些代码并且不是总有必要。但是如果你的代码真的很大,并且你需要尽可能的性能提升,它会是很好的优化。

当你通过GetComponent获取一个组件或一个变量时,unity必须从游戏物体里找到正确的组件。这时你便能通过一个缓存组件引用到一个私有变量。

将:

void Update () {

    transform.Translate(new Vector3(0, 0, 5));

}

转换为:

private Transform myTransform ;

void Awake () {

    myTransform = transform;

}

void Update () {

    myTransform.Translate(new Vector3(0, 0, 5));

}

后面的代码运行较快,因为Unity不用在每一帧寻找变换组件。同样,支持脚本组件。你可以使用GetComponent获取组件或其他快捷属性。

渲染

一个Mesh 建议使用的面数在1500~4000 之间。

一个 Mesh 建议只用一个 Material。

注意:两个Mesh结合成一个Mesh,但是却使用两个Material,并不会提高效能。

如果要提高效能必须把这两个Mesh的Material也合并成一个。

换句话说,一个Mesh使用多个Material 和一个Material 使用多个render,其实耗能是差不多的。

所以,尽可能的让物件共用相同的Texture 才是提升效能的根本之道。

  

把物体设为static可以提高渲染效率,缺点是不能使用动态uv(可能还有别的缺点,不过没试过)

  

算法

1. 尽量避免每帧处理

比如:

function Update() { DoSomeThing(); }

可改为每5帧处理一次:

function Update() { if(Time.frameCount % 5 == 0) { DoSomeThing(); } }

2. 定时重复处理用 InvokeRepeating 函数实现

比如,启动0.5秒后每隔1秒执行一次 DoSomeThing 函数:

function Start() { InvokeRepeating("DoSomeThing", 0.5, 1.0); }

3. 优化 Update, FixedUpdate, LateUpdate 等每帧处理的函数

函数里面的变量尽量在头部声明。

比如:

function Update() { var pos: Vector3 = transform.position; }

可改为

private var pos: Vector3; function Update(){ pos = transform.position; }

4. 主动回收垃圾

给某个 GameObject 绑上以下的代码:

function Update() { if(Time.frameCount % 50 == 0) { System.GC.Collect(); } }

   

5. 运行时尽量减少 Tris 和 Draw Calls

预览的时候,可点开 Stats,查看图形渲染的开销情况。特别注意 Tris 和 Draw Calls 这两个参数。

一般来说,要做到:

Tris 保持在 7.5k 以下

Draw Calls 保持在 20 以下

6. 压缩 Mesh

导入

3d 模型之后,在不影响显示效果的前提下,最好打开 Mesh Compression。
Off, Low, Medium, High 这几个选项,可酌情选取。

7. 避免大量使用 Unity 自带的 Sphere 等内建 Mesh

Unity 内建的 Mesh,多边形的数量比较大,如果物体不要求特别圆滑,可导入其他的简单3D模型代替。

8. 优化数学计算

比如,如果可以避免使用浮点型(float),尽量使用整形(int),尽量少用复杂的数学函数比如 Sin 和 Cos 等等。

使用#pragma strict

现在问题是,你通常不会意识到你在使用动态类型。#pragma strict可以解决这个问题!简单的添加#pragma strict在脚本顶部,之后Unity将禁用脚本的动态类型,强制你使用静态类型。如果有一个类型未知,Unity将报告编译错误。下面,foo将在编译时报错:

#pragma strict

function Start ()

{

    var foo = GetComponent(MyScript);

    foo.DoSomething();

}

  

使用内置数组

内置数组是非常快的。ArrayList或Array类很容易使用,你能轻易添加元件。但是他们有完全不同的速度。 内置数组有固定长度,并且大多时候你会事先知道最大长度然后填充它。内置数组最好的一点是他们直接嵌入结构数据类型在一个紧密的缓存里,而不需要任何额外类型信息或其他开销。因此,在缓存中遍历它是非常容易的,因为每个元素都是对齐的。

privatevar positions : Vector3[];

function Awake () {

    positions = new  Vector3[100];

    for (var i=0;i<100;i++)

    positions =  Vector3.zero;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Unity3D 性能优化