Get*_*awn 3 c# unity-game-engine
我有以下定义事件和委托的类。然后,我有一种触发事件的方法,如下所示:
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后,我有一个此类监听事件的类,如下所示:
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,是否可以仅在特定对象上触发事件?
因此,不要这样做:
// Trigger
OnObjectDeath(receiver);
// ---------------------------- //
void Died(GameObject go){
if(gameObject == go){
Destroy(gameObject);
}
}
Run Code Online (Sandbox Code Playgroud)
我可以做这样的事情:
receiver.OnObjectDeath();
// ---------------------------- //
void Died(){
Destroy(gameObject);
}
Run Code Online (Sandbox Code Playgroud)
我希望有一种方法,在这种情况下,Died我不必检查要在哪个对象上应用它。目前,如果我删除该if语句,那么它将应用于所有gameObjects,而不仅仅是我正在使用的实例。
您似乎在滥用案例中的事件模式。事件/侦听器的要点是,无论谁在侦听,发送方都会发送信息。
但是在您的情况下,发件人针对的是一个特定的实例,您实际上已经对其进行了引用。然后,您还可以获取该对象的组件并在其上调用一个方法。
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
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:根据您的评论,一种更合适的方法(以我的观点)将是使用Damage方法具有IDamageable接口。然后,所有应损坏的物品都应实施该方法,以使它们正确损坏。然后,您可以简单地调用带有损坏程度的Damage方法,并在需要时处理死亡。
让我们考虑一个子弹系统:
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
子弹忽略了它所击中的东西,应该不在乎。只重要的是它应该损坏多少。
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
妳去 如果需要将UI或场景管理器等其他项目通知死亡,以便他们可以执行操作,则可以让他们找到事件并注册。玩家甚至都不知道它们。