Unity3D性能优化 - Update() 的使用
个人认为在脚本方面采用面向对象的调用开发,每次在Update里面写代码的时候,你要考虑,是否值得这么做,因为我们都知道update是每一侦都会执行的,那么如果有些代码并不是每次都需要调用的,你就不应该放到update里面检测某个条件成立,然后再执行,这样就类似C语言的过程式编程了。
不知道大家是否完全了解了官方这里http://docs.unity3d.com/Documentation/ScriptReference/index.Performance_Optimization.html 所说的一样去优化你的代码。特别最后一点就是强调update里面不要加入你没有达到的方法调用。
常见的update写法莫过于:
1、判断某个时间点、或者某个bool是否为true然后执行某些方法或者调用某个方法。
- void Update()
- {
- if( b == true)
- {
- ........do something....
- }
- }
如上,应该很多人会这样写,因为读起来很好理解啊。其实这样就是掉入了消耗每一侦不必要的判断,想象一下这是一个人物身上的脚本,有N个人物,是否就要update里面N个脚本会判断N次,我好像很喜欢用N个人物来说事情,习惯了,谁叫每天看到最多的就是人呢!
那么如何解决呢???
大家仔细看我前面引用的官方文档里面最后那点,让你完全地使这个monobehaviour变成残废。其实就是这个脚本或者component变成enable = false; 你把b想象成你要在update执行的component的enable,如果它打开,那么update自然就启用了,否则让它整个脚本废掉!!!!!
所以官方提及了有2个方式:1、是否被渲染到这个物体(被摄像机照到);2、用触发器去检测和控制;
1.1 除了以上直接把这个component的enable关闭外,那么我这里需要强调就是coroutines的使用,特别是对于N秒后需要调用某些方式;或者按了某个键才做什么,否则直接返回;那么使用coroutines比你在update里面写个计时器或者判断某个键好多。
参考讨论:http://answers.unity3d.com/questions/119076/Coroutines-vs-UpdateFixedUpdateLateUpdate.html
- function Update () {
- if (!wait) {
- transform.Translate(Vector3.forward * Time.deltaTime);
- }
- else if (Time.time >= timer) {
- wait = false;
- }
- if (Input.anyKeyDown) {
- wait = true;
- timer = Time.time + 1.0;
- }
- }
以上很多人都可能会这么写,那么我们用协程如何操作了,可以StartCoroutine……
- function Start () {
- while (true) {
- transform.Translate(Vector3.forward * Time.deltaTime);
- if (Input.anyKeyDown) {
- yield WaitForSeconds(1.0);
- }
- yield;
- }
- }
那么我结合以上关闭这个component以及倒计时的使用,来实现我的目地:因为我的update方法里面需要检测是否显示某个页面,然后某个滚动条的%需要实时获取数据来改变。关闭这个页面的时候,完全让这个脚本给取消enable = false; 但是我需要延时,因为你有可能临时关闭然后马上打开,那么可以减少这之间的瞬间变来变去的消耗,采用coroutine再也合适不过了!!具体请看代码:
- using UnityEngine;
- using System.Collections;
- /// <summary>
- /// Thinkgear user interface help message.
- ///
- /// By chiuan 2012.8.18
- /// </summary>
- public class ThinkgearUIHelpMessage : MonoBehaviour {
- //the time gap that need to disable the component .
- const float _TimeToDisable = 0.2f;
- bool isNeedToDisable = false;
- #region for other call message or invoke.
- public void UnActiveObject()
- {
- isNeedToDisable = true;
- StartCoroutine("StartCheckDisable");
- }
- public void ActiveObject()
- {
- if(isNeedToDisable == true)
- {
- //because this means the coroutine has started.
- //than u need to stop it,if u wanna active this .
- StopCoroutine("StartCheckDisable");
- }
- isNeedToDisable = false;
- }
- #endregion
- IEnumerator StartCheckDisable()
- {
- yield return new WaitForSeconds(_TimeToDisable);
- if(isNeedToDisable)
- {
- gameObject.SetActiveRecursively(false);
- }
- }
- }
以上UnActiveObject的方法是在这个页面要禁止时候由其他component控制调用,这时计时器coroutine开始启动,那么如果期间没有临时执行activeObject这个方法,那么这个页面将会延时disable,同时这个页面的所有component都会uncheck掉了!
1.2****延伸
大家可以使用OnEnabel()和OnDisable()方法检测这个脚本component是否活跃状态来执行初始化或者启动某些方式运算和关闭和清理工作。