2015-12-28 21 views
2

我有以下定義事件和委託的類。然後我有觸發這樣的事件的方法:在特定實例上觸發的代表和事件

public class HealthManager : MonoBehaviour { 
    // Create the delegate 
    public delegate void ObjectDeath(GameObject go); 
    // Create the event 
    public static event ObjectDeath OnObjectDeath; 

    public static void GiveDamage(GameObject dealer, GameObject receiver, float amount){ 
     /* 
      Subtract health here 
      ... Code Snipped ... 
     */ 
     if(objectHealth.health <= objectHealth.deathHealth){ 
      // Trigger the delegate/event 
      OnObjectDeath(receiver); 
     } 
    } 
} 

然後我有這個類來監聽事件被炒魷魚是這樣的:

public class DeathListener : MonoBehaviour { 

    // Add event listeners when object gets enabled 
    void OnEnable() { 
     HealthManager.OnObjectDeath += Died; 
    } 

    // Remove event listeners when object gets disabled 
    void OnDisable() { 
     HealthManager.OnObjectDeath -= Died; 
    } 

    void Died(GameObject go){ 
     if(gameObject == go){ 
      Destroy(gameObject); 
     } 
    } 

} 

這個問題我已經是,就是它只能在特定對象上觸發事件?

所以,與其這樣:

// Trigger 
OnObjectDeath(receiver); 
// ---------------------------- // 
void Died(GameObject go){ 
    if(gameObject == go){ 
     Destroy(gameObject); 
    } 
} 

我可以做這樣的事情:

receiver.OnObjectDeath(); 
// ---------------------------- // 
void Died(){ 
    Destroy(gameObject); 
} 

我想有一種方式,其中在事件Died我沒有檢查將其應用於哪個對象。目前,如果我刪除if語句,那麼它將應用於所有gameObjects,而不僅僅是我正在使用的實例。

+0

通過說「那麼它將適用於所有的gameObjects不只是我正在使用的實例」你是指所有的場景中的對象?即使那些沒有DeathListener組件的人? –

+0

對不起,只有那些有DeathListener組件的人。 –

+0

爲什麼你讓你的事件是靜態的?請刪除靜態並查看它是否仍然銷燬其他gameObjects –

回答

3

你好像在你的情況下濫用事件模式。事件/監聽者的要點是發送者無論誰在監聽都發送信息。

但在你的情況,發件人是針對一個特定的實例,你實際上已經有一個參考。然後你可能會得到該對象的組件並調用它的一個方法。

public static void GiveDamage(GameObject dealer, GameObject receiver, float amount){ 
    /* 
     Subtract health here 
     ... Code Snipped ... 
    */ 
    if(objectHealth.health <= objectHealth.deathHealth){ 
     // Trigger the delegate/event 
     receiver.GetComponent<DeathListener>().Died(); // no need for parameter 
    } 
} 

編輯:根據您的評論,更合適的方式(在我看來)將是一個IDamageable接口與損害方法。然後,所有應該損壞的物品應該實施該方法,以便正確地損壞它們。然後,你可以簡單地調用損傷方法,如果需要的話,它會照顧死亡。

讓我們考慮一個彈頭系統:

public void Bullet:MonoBehaviour{ 
    public int damage = 10; 
    // it is hitting either from raycast or collision or else 
    void OnHit(GameObject collidedObject){ 
     IDamageable dam = collidedObject.GetComponent<IDamageable>(); 
     // if you hit a wall or no damageable item, it will be false 
     if(dam != null) { 
      dam.Damage(damage); 
     } 
    } 
} 

子彈是無視它是什麼打,應該不會在意。只關乎它應該損害多少。

public class Player : MonoBehaviour , IDamageable{ 
    int health = 20; 
    public EventHandler <EventArgs> RaiseDeathEvent; 
    protected void OnDeath(EventArgs arg){ 
      if(RaiseDeathEvent != null) RaiseDeathEvent(this, arg); 
    } 
    public void Damage(int damage){ 
     this.health -= damage; 
     if(this.health < 0){ 
      Died(); 
      OnDeath(null); 
     } 
    } 
} 

你走了。如果您需要其他項目,例如UI或場景管理員被告知死亡,以便他們可以執行某項操作,那麼您可以讓這些人找到該事件並進行註冊。玩家甚至不知道他們。

+0

我想獲得類似'instance.SendMessage(「OnObjectDeath」);',這意味着這將不會工作的方式我想要它... –

+0

我也不知道'DeathListener'是否是組件名稱。我可以被稱爲任何東西。 –

0

的問題是與靜態事件,因爲它會在整個HealthManager類的實例,所以我做了這個共享:

public class HealthManager : MonoBehaviour { 
// Create the delegate 
public delegate void ObjectDeath(GameObject go); 
// Create the event 
public event ObjectDeath OnObjectDeath; 
//this method must not be marked static also 
public void GiveDamage(GameObject dealer, GameObject receiver, float amount){ 
    /* 
     Subtract health here 
     ... Code Snipped ... 
    */ 
    if(objectHealth.health <= objectHealth.deathHealth){ 
     // Trigger the delegate/event 
     OnObjectDeath(); 
    } 
} 

}

而在DeathListener類有:

public class DeathListener : MonoBehaviour { 
public HealthManager _hm; 
void Awake(){ 
    _hm = GetComponent<HealthManager>(); 
} 
// Add event listeners when object gets enabled 
void OnEnable() { 
    _hm.OnObjectDeath += Died; 
} 

// Remove event listeners when object gets disabled 
void OnDisable() { 
    _hm.OnObjectDeath -= Died; 
} 

void Died(){ 

     Destroy(gameObject); 

} } 

現在只有每個組件的擁有者將被單獨銷燬,而不是全部在一起 請考慮co中的任何語法錯誤德,因爲我從你自己的部分代碼寫這個...

進一步說明:您甚至可以向DeathListener類中添加[RequireComponent(typeof(HealthManager))],以便在沒有健康管理員的情況下不能添加!

相關問題