Extending the Unity Editor for the Observable Pattern
Written by Alexander van der Zalm.
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!