1. 程式人生 > >unity3d 使用委託+事件 完成低耦合傳送訊息

unity3d 使用委託+事件 完成低耦合傳送訊息

        最近在自學unity3d,看了網上的一些教學視訊和小遊戲按鈕,感覺gameobject與gameobject 的訊息傳遞,程式碼耦合性很強,因為我是開發as3的用的是面向物件的MVC思想,所以看到耦合性強的程式碼就有點強迫症去修改它,以下是用委託+事件做的一個低耦合的訊息傳遞;不說廢話,進入主題奮鬥

首先建立一個簡單的場景,一個plane,放在上面的兩個cube,其中一個cube(稱為A)移動撞向另一個cube(稱為B),撞了之後A向B傳送 一個訊息,能自定義訊息的;

一個單例去儲存委託和事件,(懂as3的朋友,這個單例相當一個事件的dispacter),程式碼如下

using UnityEngine;
using System.Collections;
/// <summary>
/// 單例
/// </summary>
public class EventDispacter{


//例項化單例
private static EventDispacter instance;


//定義委託事件,它定義了可以代表的方法的型別
/**碰撞檢測*/
public delegate void CollisionHandler(DataType evt);
public event CollisionHandler CollisionHapend;  


private  EventDispacter(SingletonEnforcer enforcer){


}


public static EventDispacter getInstance()
{
if(instance==null)
{
instance=new EventDispacter(new SingletonEnforcer());
}
return instance;
}


public void sendCollisionHapend(DataType evt){
if(CollisionHapend!=null)CollisionHapend (evt);
}


}


class SingletonEnforcer {}

自定義訊息的方法如下:

using UnityEngine;
using System.Collections;


public class DataType{
//定義委託事件傳送訊息的內容,或者其他東西
private string txt;

public string Txt{
get{return txt;}
set{txt=value; }
}
}

在A  cube這個物體的指令碼中

using UnityEngine;
using System.Collections;


public class Cmain : MonoBehaviour {


//要傳遞的內容
private DataType d;


void OnTriggerEnter (Collider c){  
//print ("Cmaincrash");
//if (EventDispacter.getInstance().CollisionHapend) {
d = new DataType ();
d.Txt = "Success  to send a message!!";
   //傳送事件
EventDispacter.getInstance().sendCollisionHapend(d);
//}
}  

// Update is called once per frame
void Update () {
transform.Translate (new Vector3 (1, 0, 0)*Time.deltaTime);
}
}

在B  cube中指令碼如下:

using UnityEngine;
using System.Collections;


public class CSon : MonoBehaviour {


// Use this for initialization
void Start () {
//監聽傳送的事件
EventDispacter.getInstance().CollisionHapend+=dealFun;

}


// Update is called once per frame
void dealFun(DataType d) {
print (d.Txt);
}

void OnDestroy(){

  //移除傳送的事件

//這個移除很重要,因為unity銷燬的是隻是自身的物體,對於這種事件的引用不會回收,如果銷燬了該物體卻不移除該事件監聽的話則會提示

//該物體已經銷燬卻嘗試去連線它,而且該事件監聽一直會佔著記憶體
EventDispacter.getInstance().CollisionHapend-=dealFun;

}


}

這樣就完成了一個gameobject向另外一個或者多個gameobject傳送訊息,又不會產生強耦合的問題;

發這博文一是希望學unity3d的朋友覺得我哪裡寫得不好的話指出來,一起探討,二是激勵自己,自學需要動力啊哭