How to use Events in Unity 5

I wrote about Events a few years back. While the post is alright at covering the functionality behind the scenes, a much more straightforward approach is better most of the time.

pexels-photo (1)

Action!

.NET has the Action delegate built-in that will be enough for 90% of Event use cases and looks very neat. Actions can have 0 or more parameters so they’re very flexible.
MSDN documentation for Action<T>

A code example illuminates this the best so here’s one tha that shows all the basic operations of an Event; adding, removing, firing and receiving events.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    // Events are declared as generic Action delegates. They can have 0 or more parameters.
    public Action<int, Vector3> OnEnemyHit;
 
    // Mock-function to add a new listener. Usually you would add this on Start() for example
    public void AddListener(){
        OnEnemyHit += EnemyHit;
    }
    
    // Mock-function to remove a listener.
    public void RemoveListener(){
        OnEnemyHit -= EnemyHit;
    }
 
    // Triggering the event
    public void Update(){
        if(enemy.wasHit) {
            if(OnEnemyHit != null){
                OnEnemyHit(enemy.id, enemy.position);
            }
        }
    }
 
    // Listener
    public void EnemyHit(int enemyID, Vector3 hitPosition){
        Debug.Log("Hit enemy: " + enemyID);
        Debug.Log(hitPosition.ToString());
    }
	// Events are declared as generic Action delegates. They can have 0 or more parameters.
	public Action<int, Vector3> OnEnemyHit;

	// Mock-function to add a new listener. Usually you would add this on Start() for example
	public void AddListener(){
		OnEnemyHit += EnemyHit;
	}
	
	// Mock-function to remove a listener.
	public void RemoveListener(){
		OnEnemyHit -= EnemyHit;
	}

	// Triggering the event
	public void Update(){
		if(enemy.wasHit) {
			if(OnEnemyHit != null){
				OnEnemyHit(enemy.id, enemy.position);
			}
		}
	}

	// Listener
	public void EnemyHit(int enemyID, Vector3 hitPosition){
		Debug.Log("Hit enemy: " + enemyID);
		Debug.Log(hitPosition.ToString());
	}

As you can see it’s a very simple system so there’s not much to say. Other than use it!

Using Stopwatch to benchmark your heavy performance code

Stopwatch is a accurate and super simple utility class included in .NET that can be used for benchmarking your heavy performance code, like sorting a big list or some large calculations.

1
2
3
4
5
6
7
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
 
// Run heavy duty code...
 
stopwatch.Stop();
Debug.Log(stopwatch.ElapsedMilliseconds + " ms elapsed in running heavy duty code.");
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();

// Run heavy duty code...

stopwatch.Stop();
Debug.Log(stopwatch.ElapsedMilliseconds + " ms elapsed in running heavy duty code.");

Use C# Object Initializers

They make code much more readable than constructors. Use empty constructors and public getters/setters or public properties when you have a lot of properties you want to initialize. Compare edge2 where we insert all the variables in the constructor with the object initializer below it. Once you have more than three parameters passed in, keeping the constructor in order becomes a pain. For example changing some parameters to be optional means you have to move them so that they’re after non-optional parameters. With object initializers you can do them in any order and define yourself any time which properties should get initialized.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        // Lame old constructor
        Edge edge2 = new Edge(new Center(), new Center(), 5, 0, "edge_01", "edge_02", 7, false);
 
        // Cool and attractive object initializer
        Edge edge = new Edge()
        {
            leftCorner = new Center(),
            rightCorner = new Center(),
            name = "edge_01",
            neighborName = "edge_02",
            index = 5,
            river = 0,
            height = 7,
            isVisible = false
        };
        // Lame old constructor
        Edge edge2 = new Edge(new Center(), new Center(), 5, 0, "edge_01", "edge_02", 7, false);

        // Cool and attractive object initializer
        Edge edge = new Edge()
        {
            leftCorner = new Center(),
            rightCorner = new Center(),
            name = "edge_01",
            neighborName = "edge_02",
            index = 5,
            river = 0,
            height = 7,
            isVisible = false
        };