unity性能优化(一)

以下文字摘自:

http://blog.163.com/lnwanggang@yeah/blog/static/16533216220110143151173/

 

1.使用静态类型

当使用JavaScript很重要的优化是使用静态类型替代动态类型。Unity使用一种技术叫做类型推理的技术来自动转换JavaScript为静态类型脚本。

var foo = 5;

上面例子中的foo将自动被推断为一个整数值。因此,Unity可能使用大量的编辑时间进行优化,而不使用耗时的动态名称变量查找等。这就是为什么Unity的JavaScript执行平均速度是其他JavaScript的20倍的原因之一。

唯一的问题是有时不是所有的东西都能做类型推断,Unity将会为这些变量重新使用动态类型。通过这样,编写JavaScript代码很简单,但也会使代码运行速度变慢。

看个例子:

functionStart ()
{
    var foo = GetComponent(MyScript);
    foo.DoSomething();
}

这里foo将是动态类型,因此呼叫函数DoSomething必须要较长的时间,因为foo的类型未知,它必须弄明白是否支持DoSomething函数,如果支持,调用函数。

functionStart ()
{
    var foo : MyScript = GetComponent(MyScript);
    foo.DoSomething();
}

这里我们强制foo为指定类型,你将获得更好的性能。

2.使用#pragma strict

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

#pragma strict
function Start ()
{
    var foo = GetComponent(MyScript);
    foo.DoSomething();
}

3.缓存组件查找

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

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

将:

functionUpdate () {
    transform.Translate(0, 0, 5);
}

转换为:

privatevar myTransform :

Transform
;
function Awake () {
    myTransform = transform;
}

function Update () {
    myTransform.Translate(0, 0, 5);
}

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

4.使用内置数组

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

privatevar positions :

Vector3
[];
function Awake () {
    positions = new
Vector3
[100];
    for (var i=0;i<100;i++)
    positions[i] =
Vector3.zero
;
}

5.如果没有必要不要调用函数

最简单,最好的优化是执行最少的工作。如,当一个敌人在远处时,让他处于睡眠状态,大多时候是可行的。直到玩家靠近,可以这样处理:

functionUpdate ()
{
// Early out if the player is too far away.
    if (Vector3.Distance(transform.position, target.position)
> 100)
    return;
    perform real work work…
}

这并不是很好的方法,虽然Unity不得不在每一帧访问update函数。更好的方法是禁用这个行为直到玩家靠近。有3中方法做这个:使用 OnBecameVisible和OnBecameInvisible。这些调用与渲染系统相联系。一旦摄像机看到物体,OnBecameVisible 将被调用,不看他时,OnBecameInvisible被调用。这有时很有用。但是对于AI来讲通常是没有用的,因为你背转敌人,敌人就变成不可用了。

functionOnBecameVisible () {
    enabled = true;
}

function OnBecameInvisible ()
{
    enabled = false;
}

2.使用触发器。一个简单的球形触发器能引发惊人效果。你可以调用OnTriggerEnter/Exit,当进入你想要的作用范围。

functionOnTriggerEnter (c :

Collider
)
{
    if (c.CompareTag(“Player”))
    enabled = true;
}

function OnTriggerExit (c :
Collider
)
{
    if (c.CompareTag(“Player”))
    enabled = false;
}

3.使用协同程序。Update的问题是他在每帧都发生。很可能只需要5秒钟检查一次玩家的距离。这可以节约大量的处理周期。

 

版权所有,禁止转载. 如需转载,请先征得博主的同意,并且表明文章出处,否则按侵权处理.

    分享到:

5 thoughts on “unity性能优化(一)

    1. huangxiansheng1980

      回复 oWuFaWuTian:
      我不知道你这样说的依据是什么?有什么理论依据吗?或者是你有实际的测试?如果你有实际的测试,你测试的工程,总共的组件有多少?

      Reply
  1. fg5823820
    引用 huangxiansheng1980:

    回复 oWuFaWuTian:
    我不知道你这样说的依据是什么?有什么理论依据吗…

    两个性能不一样,但是拿直接使用transform来和GetComponent相提并论是扯淡的,直接使用transform只是因为多调用了get_Transform函数造成的开销才导致性能下降(有可能还调用了get_GameObject),而相比GetComponent这种查找函数的开销远低得多。感觉MONO的内联似乎做得不太好

    Reply
  2. fg5823820

    另外 var foo = GetComponent(MyScript);这样在3.5里即使是严格编译也是能通过,编译器也能根据参数识别出foo的类型是MyScript,除非你是这样var foo = GetComponent("MyScript");

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *