Simple behaviors with delegates and events


<

I have a "Mortality" behavior that I can attach to any game object that has health and can die. This is pretty generic, so this means it can refer to a player or character, but also to destructible objects in the scene, such as barrels and plants. As I'm still learning best practices for accomplishing specific tasks in Unity, I'd like to share my approach to this behavior. Note that this is a simplified version that you can extend to meet your needs.

The main Mortality.cs script has some variables you would expect: health (int), dead (bool), etc. The key item to note here is the use of delegates and events. By declaring delegate and event combinations (such as OnDeathEvent() and OnDeath), other objects that have this Mortality behavior can register functions to be called when these events occur. The nice thing is that this is a collection, so you can add any number of functions as listeners to these events – not just one. You just have to remember to deregister the functions when the containing object is disabled or destroyed.

using UnityEngine;
using System.Collections;

public class Mortality : MonoBehaviour
{
	public int initialHealth = 5;
	public int health { get; private set; }

	// events
	public delegate void OnDeathEvent();
	public event OnDeathEvent OnDeath = delegate {};
	public delegate void OnReviveEvent();
	public event OnReviveEvent OnRevive = delegate {};
	public delegate void OnHealthDownEvent();
	public event OnHealthDownEvent OnHealthDown = delegate {};

	void Start()
	{
		// init
		Revive();
	}

	public void Revive()
	{
		health = initialHealth;
		dead = (health <= 0);
		OnRevive();
	}

	public void DecrementHealth(int amount)
	{
		health -= amount;
		OnHealthDown();

		if (health <= 0 && !dead)
		{
			dead = true;
			OnDeath();
		}
	}
}

For example, let's say you have a Barrel.cs behavior attached to a destructible barrel game object. If you attach the Mortality.cs script to it above, then you can handle specific health and death events on the barrel like so:

using UnityEngine;
using System.Collections;

public class Barrel : MonoBehaviour 
{
	private Mortality mortality;

	void Awake()
	{
	    // store a reference to the mortality component
		mortality = GetComponent<Mortality>();
	}

	void OnEnable()
	{
	    // register this class' OnDeath() function
		mortality.OnDeath += OnDeath;
	}

	void OnDisable()
	{
	    // deregister this class' OnDeath() function
		mortality.OnDeath -= OnDeath;
	}

	void OnDeath()
	{
		// perform your specific logic here when this game object "dies"
	}
}