Event Manager in Unity - Observer Pattern on Steroids !

Whether you're working on a 2D platformer or a 3D action-adventure, Event Managers can transform the way you structure and manage your game's components. Don't forget to like, share, and subscribe for more exciting Unity tutorials and game development insights.
My UniTask Set-up Tutorial: • Use UniTask to Delay y...
Using UniTask DOTween: • Use DOTween effectivel...
How to properly DESTROY GameObject & REMOVE from the List in Unity: • How to properly DESTRO...
FREE Odin Inspector Alternative - NaughtyAttributes Unity Tips & Tricks: • FREE Odin Inspector Al...
Timeline:
0:00 Observer Pattern
3:51 Event Manager
#unity #unity3d #gamedevelopment #tutorial #c #unitytutorial #gamedev #events #programming #coding #howto #event #game #unityevents #delegates #unity2d #unityeventsystem #gameengine #unity3dtutorial #gamedesign #code #unitytutorials #gamearchitecture #games #unityc #learn #unitygametutorial #indie #beginner #multiplayer #unitytutorialforbeginners #unityevent #unity2dtutorial

Пікірлер: 78

  • @soverain
    @soverain6 ай бұрын

    I’ve seen (and made myself) many different implementations of an Event Bus, but this one is the simplest and cleverest of them. Congrats!

  • @NotJustUnity

    @NotJustUnity

    6 ай бұрын

    Thanks !

  • @mattomwit
    @mattomwit6 ай бұрын

    Nice. Well explained. Thank you for taking the time to make this video. Keep it up!

  • @NotJustUnity

    @NotJustUnity

    6 ай бұрын

    Hi, tks for watching the vid !

  • @elliottk68va
    @elliottk68va8 ай бұрын

    Awesome! Thanks for your work.

  • @NotJustUnity

    @NotJustUnity

    8 ай бұрын

    Thanks for watching !

  • @Tom2savoi
    @Tom2savoi6 ай бұрын

    Very well explained, great tutorial !

  • @NotJustUnity

    @NotJustUnity

    2 ай бұрын

    Thanks !

  • @redragon1229
    @redragon12299 ай бұрын

    Amazing tutorial. I will add that you can use enum instead of EventKey - a bit better for performance

  • @NotJustUnity

    @NotJustUnity

    9 ай бұрын

    Thanks for watching ! You can modify the pattern to suit your project !

  • @512Squared

    @512Squared

    5 ай бұрын

    I was thinking the same. You can also pass a struct as the payload.

  • @darrencook7168
    @darrencook71688 ай бұрын

    Explaining the observer pattern by asking viewers to subscribe to the channel. Smooth. Subscribed. :)

  • @NotJustUnity

    @NotJustUnity

    7 ай бұрын

    Thanks !

  • @perssontm1628

    @perssontm1628

    4 ай бұрын

    Just don't forget to unsubscribe! Otherwise errors can occur :)

  • @THEspindoctor84
    @THEspindoctor848 ай бұрын

    great video! One suggestion - please zoom in your screen on your code, but also on the diagrams. Even when I was viewing in full screen, the diagram was pretty small. And the code can also be zoomed in significantly - current we see a lot of visual studio windows that are not relevant to the video content. Again, great video and great content!

  • @NotJustUnity

    @NotJustUnity

    8 ай бұрын

    Tks for your recommendation !

  • @512Squared

    @512Squared

    5 ай бұрын

    On mobile tablets, KZread allows pinch to zoom on videos. Not sure if it's available on browser KZread, but very useful for exactly this.

  • @512Squared

    @512Squared

    5 ай бұрын

    On mobile tablets, KZread allows pinch to zoom on videos. Not sure if it's available on browser KZread, but very useful for exactly this.

  • @Imperior2398
    @Imperior23988 ай бұрын

    Helo! Love the video! You opened my eyes to newer possibilities, just have one question in the script EventManager the one shown at 4:30 in line 6, after the class name you added . Might I ask what is the and what do they do, and why are you using them? I haven't seen this in my time with code

  • @NotJustUnity

    @NotJustUnity

    8 ай бұрын

    Hi, tks for watching the video ! You can search C# generic on Google and research more about it.

  • @512Squared

    @512Squared

    5 ай бұрын

    is the 'type' operator for the event arguments. means the action must be invoked with a float as an argument, in other words, it's like passing an input parameter into a method, so when you call the method, you have to input the same type as the input parameter. This is the same, but with the event system. Great for passing information along with your announcement that an event took place. So 'hey, health changed' is the event, and the event argument can be a float for how much it has changed by.

  • @ezoray
    @ezoray6 ай бұрын

    Thanks for the video, I'm looking to implement event handling in my current project for better decoupling and was going to go with the scriptable object route. Would you recommend that approach?

  • @NotJustUnity

    @NotJustUnity

    6 ай бұрын

    Hi, I would not recommend that, I believe scriptable object is best for storing the game data and we should not include our code logic in this.

  • @ezoray

    @ezoray

    6 ай бұрын

    @@NotJustUnity Yeah I dropped that idea, I have a client message service that needs to push out a lot of different types of messages and it was a real faff creating and keeping track of it all. For now I'm just exposing a UnityEvent per message which is a lot less trouble to wire up. Thanks!

  • @NotJustUnity

    @NotJustUnity

    6 ай бұрын

    @@ezoray true, tks for watching the video !

  • @septiannabilah4779
    @septiannabilah47796 ай бұрын

    Is it possible to see the project scripts ? If it possible it would be awesome. Me myself already have implemented Scriptable event but it is getting more tedious as the project grow. Great and Clever way of implementing Event Manager BTW.

  • @MrIndiemusic101
    @MrIndiemusic1016 ай бұрын

    I have a question. So I generally like event driven programming overall. But there is one scenario Im thinking of where Im wondering whether or not its a good idea. Say you want to send an event each time a player damages an enemy. So when your attack hits you dispatch a player_damage_dealt event using your event manager. Lets say you have 100 enemies listening to this same event and the event payload contains an identifier for which enemy is hit and each enemy checks if its them that got hit before applying the dmg when responding to the event. In this scenario do you feel its more efficient to simply retrieve enemy health component of the hit enemy and apply the dmg that way. Or should I go with the event driven approach even if 99/100 enemies will end up ignoring player_damage_dealt event.

  • @JaguarPanda

    @JaguarPanda

    6 ай бұрын

    The rule ususally is: if you have direct access to components, avoid events

  • @MrIndiemusic101

    @MrIndiemusic101

    6 ай бұрын

    ​​@@JaguarPandaso I ended up writing a variant of this that allows you to assign an event to specific game object via its instance ID when registering an event. When my bullet hits an enemy it can get the game object instance id from the collider, and then trigger a HIT event given that specific instance ID. And only that game object responds to the event while other enemies on screen don't even receive the hit event. Now my bullet collision logic doesn't need to know anything about what it hit other than the instance ID of the game object it hit.

  • @mattomwit

    @mattomwit

    3 ай бұрын

    I had similar issue with playing a sound when enemy is damaged. Imagine 100 enemies playing sounds at the same time. The solution I used was to not play the sound when one was already in progress.

  • @_HoangQuangVinh
    @_HoangQuangVinh6 ай бұрын

    if my event doesnt have any pass through value, do i need to create another eventManager with no generic?

  • @NotJustUnity

    @NotJustUnity

    6 ай бұрын

    Hi, non generic version of event manager works just fine, you can create it if you want.

  • @jacobs.7925
    @jacobs.79256 ай бұрын

    Outstanding video! Do you happen to have a github repo with the code? Thank you!!

  • @NotJustUnity

    @NotJustUnity

    6 ай бұрын

    Hi, this is the code: ublic static class EventManager { private static Dictionary eventDictionary = new Dictionary(); public static void RegisterEvent(string eventType, Action eventHandler) { if (!eventDictionary.ContainsKey(eventType)) { eventDictionary[eventType] = eventHandler; } else { eventDictionary[eventType] += eventHandler; } } public static void UnregisterEvent(string eventType, Action eventHandler) { if (eventDictionary.ContainsKey(eventType)) { eventDictionary[eventType] -= eventHandler; } } public static void TriggerEvent(string eventType, TEventArgs eventArgs) { if (eventDictionary.ContainsKey(eventType)) { eventDictionary[eventType]?.Invoke(eventArgs); } } }

  • @risingforce9648
    @risingforce9648Ай бұрын

    is this approach valid for game dynamic changing scene? let say I am creating a QuestSystem and trying to find a way to communicate Data of my quest...sending events ... but also keeping the Quest in other scenes... this is an alternative to a singleton event manager? I mean... create a singleton EventManager to handle Event classes ?

  • @NotJustUnity

    @NotJustUnity

    Ай бұрын

    Hi, as you can see, the EventManager class is static, so we can use it independently from Unity Scene System. However, remember to unsubscribe the event after changing scene.

  • @risingforce9648

    @risingforce9648

    Ай бұрын

    @@NotJustUnity suscribe and unscribe ? it is automatically? or I need to do it? i useOnenable, OnDisable and sometieme ONDestoy ... however for quest I woul like to send events before hand to change the level, to check states of the quest system to other system. I think Data structure is the pain in Unity...special because Unity enforce people to use and abuse singletons and also the are tons of implemetantion of observe pattern with advantage and disadvantage of this pattern.

  • @NotJustUnity

    @NotJustUnity

    Ай бұрын

    @@risingforce9648 you have to manually subscribe and unsub those events. But I think in this case you should reference other system in your quest system for better control.

  • @mohamedmusthafa1057
    @mohamedmusthafa10578 ай бұрын

    Its Very Helpful video dude, i have One doubt im big Fan Of Observer Pattern Im using EventHandler, And Action Func , predicate frequently i explicitively place Events On Event Manager example if I Grab Pickup item when inventory full it will never accept and Never destroy So here i use predicate or func This Dictionary seems Interesting but its Flexible for return type delegates And multiple parameters?

  • @NotJustUnity

    @NotJustUnity

    8 ай бұрын

    Hi, you can absolutely modify the pattern to support multiple parameters. In here, I used Generic for the event manager to work regardless of the type, so even delegate type is supported. Thanks for watching ! If you have another question please let me know !

  • @rubinluitel158
    @rubinluitel1589 ай бұрын

    Is there a limitation on how many events/subscribers there are? And in what case can we use events versus simply referencing another game object to get data?

  • @Briezar

    @Briezar

    9 ай бұрын

    technically there aren't any limitations, just like how you can have a dictionary with thousands of keys; worst thing that could happen is that you run out of memory, but if it actually happens then there's a very high chance that the problem lies elsewhere in your code, not on the pattern itself. You can always use direct references over events to setup your data, but by referencing another class you create a dependency between them, it also means the class has public members which can be changed from the outside, making debug harder. By limiting dependency, if a bug occurs then you will know that only the container class has problems, not the 5 other classes that directly manipulate this class. As a rule of thumb, if a class doesn't need to know about another class to function, then use events, else use reference or dependency injection. Using events mean you don't care about other objects' data. E.g. The In-game HUD would need reference to the HP bar (or its child objects in general) to know which object to update, but it doesn't need to know what enemy attacked you, it only needs to know when you got hit and lose hp. So basically, use reference when you need to access class data, use events when you only need some methods of that class to be called when something happens. You would gradually understand as you code, it's not an easy to concept to grasp at first glance.

  • @NotJustUnity

    @NotJustUnity

    9 ай бұрын

    @@Briezar Tks for replying, technically there are no limitations, and yeah u will use event to reduce code dependency.

  • @AleksandrZamiatin
    @AleksandrZamiatin6 ай бұрын

    Thank you for the video! Is it possible to create an event without parameters?

  • @512Squared

    @512Squared

    5 ай бұрын

    Yes, just don't add a type after EventManager (or payload)

  • @shantanumaskeri
    @shantanumaskeriАй бұрын

    The event system class either takes no parameters or only 1 (TEventArgs) and the register, unregister, and trigger methods are created accordingly. But what if I want to pass 2 or more arguments at once. What is the workaround for that?

  • @NotJustUnity

    @NotJustUnity

    Ай бұрын

    Hi, you could wrap those parameter around a class or struct. For example: public class DamageParams { public int Value; public string Source; }

  • @shantanumaskeri

    @shantanumaskeri

    Ай бұрын

    That is one way I can definitely try out. Thanks! But does that mean the way you have implemented in your video by simply passing TEventArgs, won't work for multiple parameters? So basically having classes like: EventManager And so on and so forth....?

  • @NotJustUnity

    @NotJustUnity

    Ай бұрын

    @@shantanumaskeri The only thing that I can come up with is adding multiple parameters, like your example EventManager . In the System.Action of C# they have to manually adding generic parameters from 1 to 16 I think. If you find out a way to do it please let me know. Thanks for watching the video.

  • @shantanumaskeri

    @shantanumaskeri

    Ай бұрын

    I have just one more question/doubt If I do use multiple parameters, what will the TriggerEvent method body look like?

  • @NotJustUnity

    @NotJustUnity

    Ай бұрын

    @@shantanumaskeri it will still check for the exist key, and it will trigger the event with the payloads which are your parameters.

  • @aoliepung5692
    @aoliepung56929 ай бұрын

    Wait for Factory pattern🎉

  • @NotJustUnity

    @NotJustUnity

    9 ай бұрын

    Already in my checklist ! It will be here soon !

  • @AbdullahGameDev
    @AbdullahGameDev9 ай бұрын

    If there is Unity Event system why i need Observer pattern??

  • @NotJustUnity

    @NotJustUnity

    9 ай бұрын

    The observer pattern will help you improve communication between your classes, and ensure the open for extension but closed for modification principle.

  • @AbdullahGameDev

    @AbdullahGameDev

    9 ай бұрын

    @@NotJustUnity Thanks👍

  • @NotJustUnity

    @NotJustUnity

    9 ай бұрын

    @@AbdullahGameDev Thanks for watching !

  • @512Squared
    @512Squared5 ай бұрын

    Probably better to pass a struct as the payload, that way your passing values, not references, no?

  • @NotJustUnity

    @NotJustUnity

    2 ай бұрын

    You could pass a struct if you want, there are some cases that references are needed, for example, if you want to store that reference in the object that handle the event.

  • @512Squared

    @512Squared

    2 ай бұрын

    @@NotJustUnity fair enough

  • @kantagara
    @kantagara9 ай бұрын

    A better way would be to just remove the enum completely and just rely on the type itself. Because, the dictionary itself is re-created for each of the type you pass it for. So it should literally only be: public static class EventSystem where T : EventArgs { private static event Action Action; public static void Subscribe(Action action) => Action += action; public static void Unsubscribe(Action action) => Action -= action; public static void Invoke(T parameters) => Action?.Invoke(parameters); } And that's it.

  • @kantagara

    @kantagara

    9 ай бұрын

    If you don't believe me ( I didn't believe it as well :D ) Run this code snippet and be blown away: using System; using System.Collections.Generic; public class Program { public static void Main() { EventSystem.Subscribe(x => Console.WriteLine("FSA")); EventSystem.Subscribe(x => Console.WriteLine("BLA")); Console.WriteLine(EventSystem.Actions.Count); } } public class Bla : EventArgs{ } public class Sla: EventArgs{ } public static class EventSystem where T : EventArgs { public static readonly Dictionary Actions = new Dictionary(); public static void Subscribe(Action action) { var key = typeof(T); if (!Actions.ContainsKey(key)) { Actions[key] = action; } else { Actions[key] += action; } } public static void Unsubscribe(Action action) { var key = typeof(T); if (Actions.ContainsKey(key)) { Actions[key] -= action; if (Actions[key] == null) { Actions.Remove(key); } } } public static void Invoke(T parameters) { var key = typeof(T); if (Actions.ContainsKey(key)) { Actions[key]?.Invoke(parameters); } } }

  • @NotJustUnity

    @NotJustUnity

    9 ай бұрын

    I would not follow this approach, the key is needed incase for payload duplication, if you want to send 2 events with same payload but different handlers, you would not be able to do it.

  • @soverain

    @soverain

    6 ай бұрын

    Very clever indeed!

  • @petewuckert
    @petewuckert8 ай бұрын

    "promo sm"