Шина событий (Event Bus). Unity

Поделиться
HTML-код
  • Опубликовано: 4 окт 2024
  • #events #unity
    Фикс ошибки ниже !
    Система событий в unity с использованием шины событий (event bus)
    При создании видео немного не досмотрел и допустил пару ошибок
    1. Забыл добавить оператор НЕ (!) в условии в методе Unregister
    !_receiverHashToReference.ContainsKey(receiverHash)
    2. Из-за дублирования хэш кодов отписка на самом деле не происходила. Спасибо комментарию от пользователя [hang du]
    Код с исправленной версией можно найти тут:
    github.com/Lek...
    Спасибо всем, кто смотрит и, тем более, проверят код из видео !

Комментарии • 29

  • @blackphoenix1343
    @blackphoenix1343 10 месяцев назад +8

    I dont understand anything but your code looks cleaner and better than most of the code i see from people in my country.

  • @dimabb4972
    @dimabb4972 Год назад +10

    Спасибо за такой контент, редко встретишь на ютубе людей, которые умеют нормально рассказать про проектирование. Желаю развития каналу и жду новых видео!

  • @MeaNX
    @MeaNX 9 месяцев назад +1

    Невероятный канал, выражаю благодарность автору и желаю успеха!

  • @forcesoftheevil9252
    @forcesoftheevil9252 Год назад +3

    Этот event bus проклятый service locator!!! Спасибо за видео))0)

    • @leksaysdevelopment7423
      @leksaysdevelopment7423  Год назад

      Ну она не выдает инстансы объектов по запросу и служит для передачи эвентов. А вот вопрос как прокидывать зависимости в нее и на нее, какие события нужно там создавать и прочие моменты уже лежат на плечах разработчика. Хотя, конечно, event bus дает возможность творить фигню. Но как инструмент, которые решает конкретную задачу, вполне себе норм.

    • @Vladislav-Listev
      @Vladislav-Listev Год назад

      @@leksaysdevelopment7423 вместо того, чтобы выдавать любые сервисы, выдает любые ивенты, а так одно и то же

  • @КлимНуралин-у4у
    @КлимНуралин-у4у Год назад +11

    Я щас на первой минуте (уже на третьей) сижу, и мне интересно. А как event bus решает проблему удобочитаемости, если ничего концептуально не изменилось? Мы понять кто подписался на C# событие никак не можем, можем жмакнуть Shift + f12 и так узнать но это не решение. Event Bus даёт нам совершенно тоже самое, сущность которую мы имеем на которую могут подписываться и мы хз кто подписывается (т.е. чтобы понять кто подписался мы идём shift + f12 в шину и там shift + f12 на метод subscribe чтобы знать кто это был). Соответственно пользователи шины тоже хз на кого они подписываются включая источника сообщений хз кому он отправляет сообщения. Это плохая идея в ООП потому что: контракт отправителя сообщения, роль отправителя в системе становится неявным для пользователей, сложно прочесть из точки вызова события кого он там триггерит

    • @sergey8513
      @sergey8513 7 месяцев назад

      А как вы предложили бы сделать? Просто, критика справедлива, однако, без альтернативного решения, она не полна)

  • @alexsklyarov6792
    @alexsklyarov6792 Год назад

    У Макса Крюкова как-то проще все, субъективно... Спасибо за контент)

  • @antonkorshunov4979
    @antonkorshunov4979 10 месяцев назад

    Красиво

  • @CoolinarGameDeveloper
    @CoolinarGameDeveloper Год назад +1

    Ты сказал что обычные события неудобно дебажить и этому поможет event bus, но по ощущениям если бы ты сам им пользовался то понял бы что он только все усложняет)

    • @leksaysdevelopment7423
      @leksaysdevelopment7423  Год назад

      Ну тут, наверное, дело вкуса. Мне не очень прикольно, когда у меня на какой-то объект 100500 зависимостей в инспекторе или через конструктор прокидывается. Количество кода в одном классе сильно увеличивается и нужно четко прослеживать связь. С шиной же мне удобнее, т.к. я под каждый тип события создаю нужную структуру и пользуюсь. По юзингам можно разобрать что и где. И тут нужно понимать, что я не призываю абсолютно все покрывать шиной. Если так делать то да, можно утонуть в разных шиновых событиях . Тут, как и везде, нужно думать, для чего применять шину, а где можно обычными событиями обойтись.

    • @Vladislav-Listev
      @Vladislav-Listev Год назад

      @@leksaysdevelopment7423 у тебя не будет 100500 зависимостей, у тебя будет только ссылка на объект, который вызывает ивент. А то, что ты сделал в видео - это очередной сервис локатор

  • @king_fox_3106
    @king_fox_3106 4 месяца назад

    Сначала было ничего не понятно, потом стало еще более не понятно, а потом когда код начал писать, осознал что это =D
    Если честно, выглядит этот паттерн так, что им можно наоборот только сильнее запутать/запутаться. Но преймущества очевидны и их больше, чем неудобство оформления. Я думаю, если покумекать, то можно найти более универсальное и приемлемое решение для подобного паттерна.

  • @hangdu-f3p
    @hangdu-f3p Год назад +3

    I have found an issue with the code in the video: the UnRegister() function doesn't seem to work. After investigation, I discovered that the reason for this is a duplicate HashCode, which is causing the previously registered event to be overwritten. Could you please let me know if I made any mistakes?

    • @leksaysdevelopment7423
      @leksaysdevelopment7423  Год назад +1

      Thanks for pointing out the problems in the code ! I added the corrected version to the description under the video

    • @hangdu-f3p
      @hangdu-f3p Год назад +1

      @@leksaysdevelopment7423 I appreciate your thoughtful reply. Your video is excellent and I can tell that you put a lot of effort into it. It was very informative and helpful. Thank you so much!

    • @HizusHiz
      @HizusHiz Год назад

      @@leksaysdevelopment7423 Ошибка не исправлена, так как в целом нельзя использовать GetHashCode() как уникальный ключ (один-к-одному). То есть, если попытаться зарегистрировать два разных получателя событий, у которых будет одинаковый hash code, то второй получатель не будет зарегистрирован. Для исправления необходимо объявить private Dictionary _receiverHashToReference и доработать Register() и Unregister()

    • @leksaysdevelopment7423
      @leksaysdevelopment7423  Год назад +1

      ​@@HizusHiz Действительно, может получиться так, что мы получим коллизию хэшей. И это привет к замене одного ресивера на другого. Но, если использовать предложенное вами решение, то для каждого варианта хэша нужно создавать массив. С учетом, что хэши совпадают довольно редко, наверное, это будет несколько лишним. Если проблема заключается в том, что каждому ресиверу нужен свой уникальный Id, то можно просто использовать Guid. Поэтому, я, наверное, буду использовать строку гуида в качестве ключа. Свое решение залил на гит. Если будут какие-то дополнения, буду рад новым комментам.
      Спасибо что обратили внимание на эту проблему !

  • @timofeypopov9844
    @timofeypopov9844 6 месяцев назад

    Как быть если у вас есть несколько экземпляров RedEvent и нужно подписаться на события конкретного экземпляра?

  • @aarontower
    @aarontower Год назад

    Было бы не плохо рассказать почему BusHolder - это плохо в этом случае... Из за стадии инициализации? Или вообще из за его наличия, не понятно 😅

    • @leksaysdevelopment7423
      @leksaysdevelopment7423  Год назад +2

      Порядок инициализации, жизненные циклы монобехов, большое количество прямых зависимостей на холдера и неудобство работы. Мне кажется, что Event Bus лучше инициализровать отдельно и сделать его сервисом. А ссылку в объектах получать из какого-нибудь DiContainer'а.
      Есть еще подход с глобальным Event Bus'ом, доступ к которому через синглтон организовывается. Но при таком подходе тоже есть свои нюансы.

  • @andrewalexart
    @andrewalexart Год назад +6

    объяснение ужасное

  • @stanislavsh6582
    @stanislavsh6582 Год назад

    Про отписку.
    Сейчас же модно делать как-то так:
    interface IEventBus
    {
    IDisposable Subscribe(IHandler handler)
    }
    class Unsubscriber : IDisposable
    {
    Action _usubscribe;
    public void Dispose();
    // ну и там где-нибудь Dispose-паттерн
    }
    Не хочется весь листинг фигачить, но суть я думаю ясна. Шина, возвращает отписчика. Тот кто подписался - может при вызове Dispose автоматом отписываться.