Extending the Unity Editor for the Observable Pattern

Written by Alexander van der Zalm.

Published on 09 August 2018.
Recently I have been on a quest to discover and understand as many programming design patterns as I can. This happened after I had a huge light bulb moment where I realized that programming design patterns could actually dramatically shift my thinking, especially with regards to game design. One of those patterns that I really like is the Observable pattern or a reactive pattern. It felt like a massive paradigm shift to be able add this to my conceptual programming framework. It allows for a much simpler and cleaner integration for events, such as leveling up or achievements. Unfortunately while trying it out in Unity3D I realized that C# properties, which is a pretty straightforward way to implement this pattern, does not play nicely with the Unity3D Inspector Editor. Hence I developed a neat little property attribute to address the issue.

What is the Observeable Pattern?

In Game Programming it is very typical to work with update loops in which you run your code every frame. This is great for things that need to happen often and especially every frame, such as drawing all your game objects or choosing the right animation frame in regards to the state of a game object. However every time that you have a situation where something needs to happen only in a specific situation, or every so often you could benefit from applying the observable/reactive pattern.

First of all lets make a distinction between:

  • a trigger,
  • a condition
  • and the actual code block to execute. 

In the game loop you trigger your condition every frame and if it is successful you run the code block. However in theory you could also trigger your condition in more specific situations, so that ideally it is called far less frequent. A more specific trigger condition could be on a value change or upon a collision. If your condition check is expensive this could potentially be a performance gain, if you end up calling it less often.

In C# triggering a condition upon a value change is easily done by using adding your condition to the set part of a property. Like so:

private int myPropVar;
public int MyProperty
{
    get { return myPropVar; }
    set { myPropVar = value; CallMeWhenChangedTrigger(); }
}

*Note that you might want to make this slightly more sophisticated by checking if the value for example actually changed before you do your condition check.

With generic delegates, lambdas, actions and funcs this type of pattern is easily extendable to support any type of condition and code blocks to execute.

In fact with you could easily embed the condition in the execution of your code block. However personally I like to separate the condition from the actual code block logic, so that the conditional logic can more easily be reused.

Observeable Pattern in Unity3D

That is all great, however as you may know when you are developing in Unity the editor does not normally support the display of properties inside the inspector. This can be fixed if you make your property work with a private variable that has a [SerializeField] PropertyAttribute which will serialize it and that makes it visible to the Editor Inspector.

Property variable visible and editable in inspector

[SerializeField]
private int myPropVar;
public int MyProperty
{
    get { return myPropVar; }
    set { myPropVar = value; CallMeWhenChangedTrigger(); }
}

Of course this means that when you change the value inside the inspector, the condition will not be tested and therefor your code block execution will not happen.

The magic Unity3D propertyattribute

Wouldn’t it be great if if you could add another property attribute to the variable that you want to observe so that it calls your conditional codeblock whenever it is changed?

[OnChangedCall("CallMeWhenChangedTrigger")]
[SerializeField]
private int myPropVar;
public int MyProperty
{
    get { return myPropVar; }
    set { myPropVar = value; CallMeWhenChangedTrigger(); }
}

This is where the property attribute [OnChangedCall(“myfuncname”)] comes to the rescue! It allows you to call a function whenever the value has changed by using a little reflection magic to find the method by matching name to the string argument. 

Below you can find the implementation that supports no argument functions, functions with multiple arguments (only constant compile time known) and runtime criteria (such as only trigger when in playmode or not in playmode.

If you like it feel free to use this in your own project! 

Instructions for the gist. Just add the first cs file to your project. For an example of how to use it see the second cs file. The gif above shows what happens when you add the monobehavior test script to your editor.

Thanks for reading!

Isn’t that cool? I hope you enjoyed this little article! If so or if you found a bug, feel free to leave a comment below!