Finding Good Patterns for Game Development
Like this post? You might like BentoBlox too — check out the game here on the App Store.
The Observer Pattern has driven a lot of my thinking as a mobile app developer on a few recent projects.
The pattern lends itself well to the task of reducing state and managing data flow.
Game development poses a whole set of challenges that don’t appear in ordinary e-commerce iOS or Android apps, but the observer pattern comes in handy for things like scene management when you’re developing games in Unity.
The Pattern
On an abstract level the pattern consists of subjects which maintain a lists of observers which they notify automatically of any state changes.
In my implementation, an observer can be any method:
private void DoSomething() {
// Do Something...
}
And a subject can be any Action
:
public event Action AfterSceneLoad;
Adding an observer to a subject is as simple as:
AfterSceneLoad += DoSomething;
In the context of a Unity project, this can be tremendously useful for, say, hooking into specific points in the scene lifecycle. For example, subjects can notify observers after a scene loads and before it unloads.
public class SceneController : MonoBehavior
{
public event Action BeforeSceneUnload;
public event Action AfterSceneLoad;
}
ThisSceneController
handles transitioning between individual scenes. Observers are notified every time a scene loads, and again just before a scene unloads.
To provide some consistent structure for classes that hold references to observers, I also create a simple interface for them implement:
public interface IObserver
{
void SetupObservers();
void DismantleObservers();
}
I add observers to relevant subjects in SetupObservers
. To avoid memory leaks, I remove the same observers in DismantleObservers
, which I make sure is called before any scene unloads:
public class MainMenuController : MonoBehavior, IObserver,
{
override void Awake()
{
SetupObservers();
SceneController.Instance.BeforeSceneUnload += DismantleObservers;
} public void SetupObservers()
{
SceneController.Instance.AfterSceneLoad += DoSomething;
} private void DoSomething() {
// Do Something...
} public void DismantleObservers()
{
SceneController.Instance.BeforeSceneUnload += DoSomething;
}}
The Takeaway
This pattern is especially useful in the context of a game, where interaction is driven from within the game (game objects interacting with each other, AI/enemies executing their own logic, etc) and from user input. Ultimately I’d like to add some structure to my usage of the pattern so that it can scale and continue to be maintainable in a larger project.