This article is also available on Medium.
Several weeks ago, we implemented a simple event mechanism that allows us to better separate the systems in our game and avoid too-strict relationships. The first draft was meant to be very explicit and, because our class hierarchy was not as clearly defined as it is now, it was easier to use an intermediate struct, CustomEventData
, to represent the type of data that could be sent in an event.
However, this implementation is far from ideal. In particular, if we start adding more and more data types to our events, we’ll have to remember to add fields to this CustomEventData
struct and update all constructors. And differentiating between “typed” and “not-typed” events was important at first to understand the event system well, but it’s a bit user-unfriendly in the long run.
Now that we’re more fluent with C# and type casting (especially thanks to our multiple glances at polymorphism and inheritance), we can improve this system and leverage C# object
variable type! 🙂
Refactor of the EventManager
class
The new class I propose for EventManager
has two main differences with the previous one:
- typed events don’t use a
CustomEventData
class anymore, rather we’ll be using the C#object
variable type that is very “lazy” and can be casted into anything quite easily further down the road (it’s sort of like a “any type of variable is accepted here” flag ;)) - we don’t differentiate between events and typed events anymore in our trigger/listener calls: instead, we’ll take advantage of C# function overload to automatically register the event as a typed event if some data is provided, else as a plain old (non-typed) event
So here’s the full code of the new EventManager
class (that will replace the previous one):
As you can see, it still has the same overall structure and works the same way as it did before. We simply removed all usage of the CustomEventData
type and “merged” the trigger/listeners functions using overloads.
Now, we need to update the various scripts that used events to match this new system. Basically, we’ll have to:
- replace all occurrences of the
TriggerTypedEvent()
(resp.AddTypedListener()
,RemoveTypedListener()
) method with the simpleTriggerEvent()
(resp.AddListener()
,RemoveListener()
) function - replace any occurrence of
CustomEventData
instances with a basicobject
variable and then, in our listener callback functions, cast the received data into the proper type so the compiler knows what actual type the variable boils down to in the end.
Changes in the UIManager
In the UIManager
, we need to change the listeners declaration and their callback functions – the following snippet of code shows all the modified functions:
Changes in the BuildingButton
In the BuildingButton
, only the OnPointerEnter()
function changes:
Changes in the UnitManager
In the UnitManager
, we also have a couple of typed events that have to be adapted:
Conclusion
And that’s it! We can now remove completely the CustomEventData
class and we won’t have to worry about adding/removing/modifying the fields of this struct in the future!
This was a really quick interlude, just to remove this small thorn in our side while it’s still manageable 🙂
Hi,
I allready did this tutorial, but now I’m getting errors.
When I hover over the “Produce Soldier” skill button I’m experiencing a NullReferenceException caused by the SetInfoPanel(UnitData data).
This function is only called by the _OnHoverBuildingButton(object data) and here I’m a bit lost. Is this correct behaviour? Because this event is fired while not being on top of a BuildingButton… it is a SkillButton.
So my question is: How do I change this? 😀
The rest works just fine: I can create a soldier unit and the InfoPanel works correctly for a real BuildingButton.
Hello! 🙂
So I think the problem is that you’re not using the right prefab for the skill buttons 😉 If you go back to tutorial #9 (Implementing character units and skills), where we set up the display of skills (part “A skill example: unit production”) you’ll see that we have another
unitSkillButtonPrefab
for the skill buttons.This prefab is just a simple UI button (see the tuto for more details) – it doesn’t have the
BuildingButton
script so it shouldn’t trigger the “hover”/”unhover” events and the info panel should not show up.For now, I guess your code crashes because you don’t have any
UnitData
to read info from in theSetInfoPanel()
…Hope it helps! 🙂
Hi,
thanks for the hint. Yes, I used the correct SkillButtonPrefab, but as this button was a copy of the building button it looks like I forgot to delete the BuildingButton script. 🙁