Observer Pattern: Add Speed Boost Pickups With C# Events In Unity
During Game Dev Unlocked Game Jam #1, I wanted to make a relaxed, arcade-style driving game. For inspiration, I drew upon California coastal sunsets, surfer vans and a bit of Horizon Chase Turbo to keep things from getting a little too relaxed. “Electric Sunset” is the title I gave my entry.
Since the jam had a 48 hour time limit, I chose to utilize premade assets to ensure the game would get finished on time. Tiny Car Controller is a simple physics-based vehicle controller available in the Unity Asset Store. Developer David Jalbert describes its advantages over more complex vehicle controllers:
“Instead of having a body with four separate wheels, which is often needlessly complicated and prone to glitches, this controller is composed of a single rigidbody and sphere collider, similar to a character controller.”
— Tiny Car Controller (Asset Store)
Using Boost with Tiny Car Controller
TinyCarController.cs contains a public method named setBoostMultiplier(), meaning a speed boost can be temporarily applied to a vehicle from another MonoBehavior script. “Electric Sunset” was submitted to the game jam with persistent speed boost objects in the form of electric orbs, each of which had an attached PowerBoost.cs script handling the pickup interaction with the surfer van.
It might seem natural to write code where OnTriggerEnter() is used to obtain a reference to the colliding surfer van for access to the vehicle controller’s setBoostMultiplier() method.
C# Events, Delegates and the Observer Pattern
The Observer Pattern can be used with C# Events as a lightweight notification system that decouples the object sending a message from the object receiving it. In the below revision of PowerBoost, the System namespace is used to access the Action delegate to define OnBoostEvent. This boost event is invoked every time the surfer van collides with an electric power up.
Keen readers may have noticed the reference to TinyCarController is gone in the revised PowerBoost script. The dependency between the two components has been intentionally broken. Instead, a PowerBoostCollector.cs script can be used to:
- Handle the surfer van’s subscription to OnBoostEvent
- Execute the business logic inside method HandleBoost() when the event is triggered
Each electric power boost object is assigned to PoweBoostCollector’s List field via the Unity inspector, then subscribed within the for each loop.
Why do I prefer this event-based implementation over the original?
Imagine if a UI element were to display a count of the total electric orbs picked up. To do this, a new method called HandleBoostUI() could be subscribed to the existing OnBoostEvent. When the surfer van picks up a power boost object, both the surfer van’s speed would be updated as well as the UI. Without the Observer Pattern, the likelihood of working with highly coupled, interconnected spaghetti code becomes more likely.
Thanks for reading my post.