I have a few questions on using events as I have not used them much and am now in need for such a system. I have a ship with multiple subsystems (computer core, engine, shields, etc) and want to hook up my UI elements to change as the subsystems are damaged, below is my current implementation of events for this system.
public class CombatUI
{
private GUIText computerCoreDamageIndicator;
private GUIText engineCoreDamageIndicator;
private GUIText weaponSystemDamageIndicator;
public void Observe(Ship ship)
{
ship.CCDH += new Ship.ComputerCoreDamageHandler(UpdateDamageIndicator);
ship.ECDH += new Ship.EngineCoreDamageHandler(UpdateDamageIndicator);
ship.WSDH += new Ship.WeaponSystemDamageHandler(UpdateDamageIndicator);
}
private void UpdateDamageIndicator(GUIText uiElement, float amount)
{
// TODO: Change value the indicator shows.
}
}
public class Ship
{
public event ComputerCoreDamageHandler CCDH;
public delegate void ComputerCoreDamageHandler(GUIText uiElement, float amount);
public event EngineCoreDamageHandler ECDH;
public delegate void EngineCoreDamageHandler(GUIText uiElement, float amount);
public event WeaponSystemDamageHandler WSDH;
public delegate void WeaponSystemDamageHandler(GUIText uiElement, float amount);
...
}
My issue is that using this method I need to create a new event, delegate, etc for every subsystem I have. Would there be a better method to implement this or am I on the right track?
No you don't. a delegate is simply a signature. You create ONE delegate per signature that you need.
public delegate void HandleActionDelegate(GUIElement element, float damageAmount);
public class Blah {
public event HandleActionDelegate EngineDamaged;
public event HandleActionDelegate ShieldDamaged;
}
In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.
public void ObserveSelf(Ship ship)
{
Debug.Log("Adding subsystems...");
ship.computerCoreDamage += new Ship.DamageHandler(UpdateDamageIndicator);
ship.engineCoreDamage += new Ship.DamageHandler(UpdateDamageIndicator);
ship.weaponSystemDamage += new Ship.DamageHandler(UpdateDamageIndicator);
ship.sensorSystemDamage += new Ship.DamageHandler(UpdateDamageIndicator);
ship.shieldEmitterDamage += new Ship.DamageHandler(UpdateDamageIndicator);
ship.shieldStrengthDamage += new Ship.DamageHandler(UpdateDamageIndicator);
ship.hullStrengthDamage += new Ship.DamageHandler(UpdateDamageIndicator);
Debug.Log("Finished adding subsystems...");
}
private void UpdateDamageIndicator(GUIText uiElement, float amount)
{
Debug.Log("Added a subsystem with element ID: " + uiElement.GetInstanceID());
}
}
public class Ship
{
public event DamageHandler computerCoreDamage;
public event DamageHandler engineCoreDamage;
public event DamageHandler weaponSystemDamage;
public event DamageHandler sensorSystemDamage;
public event DamageHandler shieldEmitterDamage;
public event DamageHandler shieldStrengthDamage;
public event DamageHandler hullStrengthDamage;
public delegate void DamageHandler(GUIText uiElement, float amount);
...
}
I can't find anything wrong with my code compared to the myriad of examples I have looked up. It seems to just skip over the += lines.
Just as a side note, there's a shortcut you can use with newer versions of C# where you can skip declaring the delegate type for arbitrary events:
public event Action<GUITextElement,float> CCDH;
The main thing you lose is the generation of parameter names on auto-generated handler functions. This is acceptable though if your handlers are declared using lambda style.