Unity3D的Delegate和SendMessage的性能差测试,以及Delegate在多线程使用要注意的小问题

一、回顾前面写的关于Delegate的消息传送优化文章,http://blog.csdn.net/chiuan/article/details/7883449 

下面的代码是做一个简单的Delegate和SendMessage之间的优化性能差距测试:

 

[csharp] view plaincopyprint?
 
  1. using UnityEngine;  
  2. using System.Collections;  
  3. /// <summary>  
  4. /// Delegate basic.  
  5. /// just test Delegate && SendMessage ..  
  6. ///   
  7. /// By Chiuan 2012.8  
  8. /// </summary>  
  9. public class DelegateBasic : MonoBehaviour {  
  10.       
  11.     //define my delegate statement.  
  12.     public delegate void MyDelegate(string arg1);  
  13.       
  14.     //create my delegate object  
  15.     public MyDelegate myDelegate;  
  16.       
  17.     //need some values to debug time spent.  
  18.     bool isStart;  
  19.     float timeStart;  
  20.     int count;  
  21.       
  22.     bool isStartSendMessage;  
  23.       
  24.     // Use this for initialization  
  25.     void Start () {  
  26.         myDelegate += myFunciton1;  
  27.         //myDelegate += myFunciton2;  
  28.     }  
  29.       
  30.     // Update is called once per frame  
  31.     void Update () {  
  32.         if(isStart )  
  33.         {  
  34.             isStart = false;  
  35.             count = 0;  
  36.             timeStart = Time.realtimeSinceStartup;  
  37.             Debug.Log("Start = " + timeStart );  
  38.             for(int i= 0; i< 50000;i++)  
  39.             {  
  40.                 if(myDelegate != null) myDelegate("");  
  41.             }  
  42.         }  
  43.           
  44.         if(isStartSendMessage)  
  45.         {  
  46.             isStartSendMessage = false;  
  47.             count = 0;  
  48.             timeStart = Time.realtimeSinceStartup;  
  49.             Debug.Log("Start = " + timeStart );  
  50.             for(int i= 0; i< 50000;i++)  
  51.             {  
  52.                 this.gameObject.SendMessage("myFunciton1","",SendMessageOptions.DontRequireReceiver );  
  53.             }  
  54.         }  
  55.     }  
  56.       
  57.       
  58.     void OnGUI()  
  59.     {  
  60.         if(GUILayout.Button("INVOKE Delegate"))  
  61.         {  
  62.             isStart = true;  
  63.         }  
  64.           
  65.         if(GUILayout.Button("SendMessage"))  
  66.         {  
  67.             isStartSendMessage = true;  
  68.         }  
  69.           
  70.     }  
  71.       
  72.     void myFunciton1(string s)  
  73.     {  
  74.         count++;  
  75.         if(count == 50000)  
  76.         {  
  77.             Debug.Log("End = " + Time.realtimeSinceStartup );  
  78.             Debug.Log("Time Spent = " + ( Time.realtimeSinceStartup - timeStart ) );  
  79.         }  
  80.     }  
  81.       
  82.     void myFunciton2(string s)  
  83.     {  
  84.         //Debug.Log("myFunciton2 " + s);  
  85.     }  
  86.       
  87.       
  88. }  


大概快个10倍的样子,频繁调用和响应其他方法的时候,我们得使用Delegate的委托事件取代SendMessage。

 

 

二、在多线程Thread下使用Delegate要注意

1、我们应该知道Monobehaviour提供的一些快捷的API去调用,例如:FindObjectOfType,GameObject.Find,SendMessage,StartCoroutine……等等。

如果在其他线程去调用这些的话,那么我们肯定会遇到错误的提示,提示这些方法只能在Mainthread中调用,请把它们的构造方法放到Awake或者Start。如果是Delegate在多线程中响应了相关方法,要去启动一个Coroutine,那么绝对会报错的。

为什么呢?

1.1、记住Unity3D是有一个单线程程序,就是它有一个主线程处理各种UnityEngine中的MonoBehaviour 便捷的查找方式都只能在默认的主线程中去调用。(我的项目就涉及到多线程处理数据的问题,就遇到这种莫名其妙的错误,因为Delegate委托代理者和方法是分开的,写主线程的方法很容易会带有MonoBehaviour里U3D自带的API,目前我发现要在其他线程启动一个协程确实不太好使)

 

2、在Thread中的Delegate响应去使某个对象,这个对象又是在MonoBehaviour中Awake或者Start初始化的话,很容易造成空引用的错误。

posted @ 2014-06-14 11:57  TouchAfflatus  阅读(753)  评论(0编辑  收藏  举报