如何订阅从任何类型X的实例/对象触发的事件
本文关键字:对象 事件 实例 任何 类型 何订阅 | 更新日期: 2023-09-27 18:10:16
我目前正在制作一个小型游戏引擎,我有点困在寻找正确的模式。首先,这里有一些代码片段来理解我想要实现的目标:
-
单位:技能施法者/目标(投掷或接收技能)
public class Unit { public string Name { get; set; } // Unit name public List<BaseAbility> MyAbilities{get; set;} // abilities that an unit has. }
-
The Ability:
public abstract class BaseAbility { public string Name {get; set;} // ability name public Unit Caster { get; set; } // ability caster (owner) public List<BaseEffect> EffectList {get; set;} // effects that an ability possess // apply all effects that this ability has on the selected target public virtual void DoAbility(Unit target) { foreach (BaseEffect eff in this.EffectList) { eff.CalculateEffect(target); } } // here we gonna subscribe to some events public abstract void initListeners(); }
-
The Effect:
public abstract class BaseEffect { public BaseAbility Owner { get; set; } // each effect belong to an ability protected string Name { get; set; } // effect name public EventDispatcher Event { get; set; } // the event to dispatched when this effect is called or used //apply effect on target public virtual void CalculateEffect(Unit target) { // Do Stuffs here like damage and poison etc etc this.Event.DispatchMyEvent(); } }
-
事件调度器:
public class EventDispatcher { private object mySender; private EffectEventArgs myArgument; public delegate void EventHandler(object sender, EffectEventArgs argument); public event EventHandler OnMyEvent; public EventDispatcher(object sender, EffectEventArgs argument) { this.mySender = sender; this.myArgument = argument; } public void DispatchMyEvent() { if (OnMyEvent != null) { OnMyEvent(this.mySender, this.myArgument); Debug.WriteLine("event has been raised"); } } }
-
Effect事件参数:
public class EffectEventArgs : EventArgs { private Unit target; // target affected by effect // not sure if we even need this EffectEventArgs ?! public EffectEventArgs(Unit unit) { this.target = unit; } }
现在我要为模拟创建2个效果,2个技能和2个单位:
-
火焰效果:
public class FireEffect : BaseEffect { public FireEffect(BaseAbility effectOwner) { this.Owner = effectOwner; this.Name = "Fire"; } public override void CalculateEffect(Unit target) { // set the event here (to get the target as argument for the event) this.Event = new EventDispatcher(this.Owner, new EffectEventArgs(target)); base.CalculateEffect(target); } }
-
风效果:与火效果相同,但名称和事件不同,应用的效果也不同。
-
火球技能:
public class FireBall : BaseAbility { public FireBall(Unit caster) { this.Name = "FireBall"; this.Caster = caster; this.EffectList = new List<BaseEffect>(); this.EffectList.Add(new FireEffect(this)); // fire ball ability has "FireEffect" as effect } public override void DoEffect(Unit target) { base.DoEffect(target); } }
-
两个单位,假设:"龙"作为单位=>有火球(技能)并且会命中=>"少林风之师"作为单位拥有被动技能"风之怒"
-
风怒:
public class PassiveAbility : BaseAbility { public PassiveAbility(Unit caster) { this.Name = "WindFury"; this.Caster = caster; this.EffectList = new List<BaseEffect>(); this.EffectList.Add(new WindEffect(this)); this.initListeners(); // subscribe to events (aka add listeners) } public override void DoEffect(Unit target) { base.DoEffect(target); } // THE MAIN PROBLEM : public override void initListeners() { // here i need to subscribe to an event fired from any Instance/Object of type FireEffect so that the targeted Unit // can react to the Unit caster (kind of counter attack) // to resume this , it should follows this logic : // if any Ability has The effect(FireEffect => FireBall for example) was casted // on this Unit thats possess this passive, react to it and counter with (WindEffect) // otherwise put : when our dragon or Ryu or even Sasuke throw an ability with // a FireEffect on our friend "Shaolin" ,he should react to it // and send the attacker flying with a powerfull WindEffect } public void CallBack(object sender, EffectEventArgs e) { BaseAbility ab = (BaseAbility)sender; this.DoEffect(ab.UnitCaster); // hit the unit caster back (revenge) } }
请注意,我们可以在这个游戏或模拟中有这么多龙和少林,任何被动的持有者(单位)应该只对攻击者(单位)做出反应。
编辑:(重述主要问题)
如何订阅通过PassiveAbility.initListeners()到一个事件从任何实例类型的FireEffect(使用FireEffect的能力)?提前感谢您的支持和贡献。
尤尼斯
为FireEffect
添加一个静态EventDispatcher并订阅。
public class FireEffect : BaseEffect
{
public static EventDispatcher FireEffectEventDispatcher = new EventDispatcher(null,null);
public FireEffect(BaseAbility effectOwner)
{
this.Owner = effectOwner;
this.Name = "Fire";
}
public override void CalculateEffect(Unit target)
{
// set the event here (to get the target as argument for the event)
FireEffectEventDispatcher.mySender = Owner;
FireEffectEventDispatcher.myArgument = new EffectEventArgs(target);
// Fire the event
FireEffectEventDispatcher.DispatchMyEvent();
//If you still want the base effect firing.
base.CalculateEffect(target);
}
}
要做到这一点,你还需要改变你的EventDispatcher
,让你在构造后设置发送者/参数(不能够无论如何没有任何意义-这是一个无用的限制)。
EventDispatcher
实现。如果可以在事件触发期间更合理地设置事件参数,那么在构造函数中设置事件参数是没有意义的。