unity 脚本优化

来源:互联网 发布:大数据概述及其趋势 编辑:程序博客网 时间:2024/06/11 02:01

Performance Optimization

性能优化

When using JavaScript the most important optimization is to use static typing instead of dynamic typing. Unity uses a technique called type inference to automatically convert JavaScript constructs to statically typed code without you having to do any work.

使用JavaScript时最重要的优化是使用静态类型而不是动态类型。统一使用一种称为类型推断的技术来自动将JavaScript构造转换为静态类型代码不用你做任何工作。

1,Use Static Typing

using UnityEngine;using System.Collections;public class example : MonoBehaviour {    public int foo = 5;}

In the above example foo will automatically be inferred to be an integer value. Thus Unity can apply a lot of compile time optimizations, without costly dynamic name variable lookups etc. This is one of the reasons why Unity's JavaScript is on average around 20 times faster than other JavaScript implementations.

在上面的例子中foo将自动推断出一个整数值。因此团结可以应用很多编译时优化,没有昂贵的动态变量名称查找等。这是一个团结的原因的JavaScript是平均20倍左右的速度比其他的JavaScript实现。

The onlyproblem is that sometimes not everything can be type inferred, thus Unity will fall back to dynamic typing for those variables. By falling back to dynamic typing, writing JavaScript code is simpler. However it also makes the code run slower.

唯一的问题是,有时候并不是所有可以类型推断,因此统一将退回这些变量的动态类型。回落到动态类型,编写JavaScript代码更简单。但是它也使代码运行得更慢。

Let's see some examples.

using UnityEngine;using System.Collections;public class example : MonoBehaviour {    void Start() {         Component <span style="font-family: Arial, Helvetica, sans-serif; color: rgb(34, 34, 34); font-size: 8pt; line-height: 17px;">foo = GetComponent<MyScript>();</span>        foo.DoSomething();    }}
Here foo will be dynamically typed, thus calling the function DoSomething takes longer than necessary - because the type of foo is unknown, it has to figure out whether it supports DoSomething function, and if it does, invoke that function.
这里foo将动态类型,从而调用函数DoSomething需要更长的时间比必要的——因为foo的类型是未知的,它必须弄清楚它支持DoSomething功能,如果是这样,调用该函数。

using UnityEngine;using System.Collections;public class example : MonoBehaviour {    void Start() {        MyScript foo = GetComponent<MyScript>();        foo.DoSomething();    }}
Here we're forcing foo to be of specific type. You will get much better performance.
在这里我们迫使foo的特定类型。你会得到更好的性能。

 2,Use pragma strict

Now the problem is of course, that you don't usually notice when you are using dynamic typing. #pragma strict to the rescue! Simply add #pragma strict at the top of a script and Unity will disable dynamic typing in that script, forcing you to use static typing. Wherever a type is not known, Unity will report compile errors. So in this case, foo will produce an error when compiling

当然,现在的问题是,你通常不会注意到当你使用动态类型。# pragma严格救援!只需添加# pragma严格脚本的顶部和统一将禁用动态类型的脚本,强迫你使用静态类型。无论一个类型是未知的,统一将报告编译错误。所以在这种情况下,foo编译时将产生一个错误

using UnityEngine;using System.Collections;public class example : MonoBehaviour {    void Start() {        MyScript foo = GetComponent<MyScript>() as MyScript;        foo.DoSomething();    }}

3,Cache component lookups

缓存组件查找

Another optimization is caching of components. This optimization unfortunately requires a bit of coding effort and is not always worth it. But if your script is really used a lot and you need to get the last bit of performance out of it, this can be a very good optimization.

另一个优化缓存组件。这种优化不幸的是需要一些编码工作,并不总是值得的。但是如果你的脚本是真的很多,你需要使用的性能,这是一个很好的优化。

Whenever you access a component through GetComponent or an accessor variable, Unity has to find the right component from the game object. This time can easily be saved by caching a reference to the component in a private variable.

当你访问一个组件通过GetComponent或一个访问器变量,团结必须找到合适的组件的游戏对象。这段时间可以很容易地保存缓存的引用组件在一个私有变量。

Simply turn this:

简单地把这个:

using UnityEngine;using System.Collections;public class example : MonoBehaviour {    void Update() {        transform.Translate(0, 0, 5);    }}
Into this:

using UnityEngine;using System.Collections;public class example : MonoBehaviour {    private Transform myTransform;    void Awake() {        myTransform = transform;    }    void Update() {        myTransform.Translate(0, 0, 5);    }}
The latter code will run a lot faster since Unity doesn't have to find the transform component in the game object each frame. The same applies for scripted components, where you use GetComponent instead of the transform or other shorthand property.

后者代码将运行更快因为团结没有找到转换组件的游戏对象每一帧。同样为脚本组件,您使用GetComponent而不是转换或其他简写属性。
4. Use Builtin arrays
使用安装在内部的数组

Builtin arrays are fast, very fast, so use them.

While the ArrayList or Array classes are easier to use since you can easily add elements they don't have nearly the same speed. Builtin arrays have a fixed size but most of the time you know the maximum size in advance and can just fill it out later. The best thing about builtin arrays is that they directly embed struct data types in one tightly packed buffer, without any extra type information or other overhead. Thus iterating through is very easy on the cache as everything is linear in memory.

而数组列表或数组类更容易使用,因为你可以很容易地添加元素没有几乎相同的速度。内装式阵列固定大小,但大多数时候你事先知道的最大大小,可以后填写。内装式阵列最棒的地方是,他们直接嵌入在一个紧密的缓冲结构的数据类型,没有任何额外的类型信息或其他开销。因此遍历是非常容易的在内存中缓存,因为一切都是线性的。

using UnityEngine;using System.Collections;public class example : MonoBehaviour {    private Vector3[] positions;    void Awake() {        positions = new Vector3[100];        int i = 0;        while (i < 100) {            positions[i] = Vector3.zero;            i++;        }    }}
5. Don't call a function if you don't have to
不如果你不必调用一个函数

The simplest and best of all optimizations is to perform less work. For example , when an enemy is far away it is most of the time perfectly acceptable to have the enemy fall asleep. That is do nothing until the player comes close. The slow way of handling this situation would be:

最简单的和最重要的是优化是执行更少的工作。例如,当敌人远是大部分时间完全可以接受敌人就睡着了。什么也不做直到接近。缓慢的处理这种情况的方法是:

using UnityEngine;using System.Collections;public class example : MonoBehaviour {    public Transform target;    void Update() {        if (Vector3.Distance(transform.position, target.position) > 100)            return;            }}
This is not a good idea since Unity has to invoke the update function and you are performing work every frame. A better solution is to disabling the behaviour until the player comes closer. There are 3 ways to do this: 1. Use OnBecameVisible and OnBecameInvisible. These call backs are tied into the rendering system. As soon as any camera can see the object, OnBecameVisible will be called, when no camera sees it anymore OnBecameInvisible will be called. This is useful in some cases, but often for AI it is not useful because enemies would become disabled as soon as you turn the camera away from them.
这不是一个好主意,因为统一调用update函数和执行工作每一帧。更好的解决方案是禁用的行为,直到玩家接近。有三个方法:1。使用OnBecameVisible和OnBecameInvisible。这些电话支持绑定到渲染系统。任何相机可以看到对象,OnBecameVisible会叫,当没有摄像头看到了OnBecameInvisible会叫。这在某些情况下很有用,但往往AI也不是有用,因为敌人会成为残疾人只要你把相机远离他们。

using UnityEngine;using System.Collections;public class example : MonoBehaviour {    void OnBecameVisible() {        enabled = true;    }    void OnBecameInvisible() {        enabled = false;    }}
2. Use triggers. A simple sphere trigger can work wonders though. You get OnTriggerEnter/Exit calls when exiting the sphere of influence you want

使用触发器。一个简单的球体触发可以创造奇迹。你得到OnTriggerEnter /退出调用时你想要退出的势力范围

using UnityEngine;using System.Collections;public class example : MonoBehaviour {    void OnTriggerEnter(Collider c) {        if (c.CompareTag("Player"))            enabled = true;            }    void OnTriggerExit(Collider c) {        if (c.CompareTag("Player"))            enabled = false;            }}


3. Use Coroutines. The problem with Update calls is that they happen every frame. Quite possibly checking the distance to the player could be performed only every 5 seconds. This would save a lot of processing power.

使用协同程序。问题是,更新调用每一帧发生。很有可能检查距离玩家只能执行每5秒。这将节省大量的处理能力。


http://docs.unity3d.com/410/Documentation/ScriptReference/index.Performance_Optimization.html(原始链接)

0 0
原创粉丝点击