Pull to refresh

Comments 18

Попробуйте передавать в качестве параметра MarshalByValue тип (для этого придется сделать наследника UnityEvent с нужным типом) — будет гарантированный GC allocation. Ну и «EventBusTest» как пример использования простой шины событий. По поводу «невозможности использования C# кода в JS» — нужно положить C# код в папочки первого этапа компилирования (Standard Assets, Plugins, etc) — тогда этот код станет доступным в JS.
И не получается. Удаляется только самый первый (иногда — два) из принимающих событие объектов, а до остальных почему-то после этого событие уже не доходит. Странно? Странно и необъяснимо. Может быть, кто-то из гуру Unity подскажет мне идеологически правильный подход, но поскольку я люблю придумывать велосипеды пока на обнаружил более элегантное решение, то поделюсь, опять же, своим.

Популярная "особенность" подобных систем. Удаление объекта же приводит к отписыванию от события (вы реализовали это прошлом пункте), верно? Таким образом, внутренняя коллекция обработчиков изменяется в процессе ее обхода. А большинство коллекций на такое не рассчитаны.


К примеру, если там внутри связный список — то удаление в процессе обхода текущего элемента обычно приводит к тому, что обход списка останавливается (если нет специальной реализации этого случая).

Второй экземпляр просто некуда оказывается вписать — поле принимающего сигнал объекта не предусматривает множественности записей.

На вашей же картинке:
image

Написано "List is Empty", и кнопочки "±" намекают на то, что можно добавить несколько получателей мышкой.
Ой, мамочки! Невнимательность — моё второе имя!
Спасибо за замечание, внёс исправление в статью.
Все эти Юнитевые «штучки» только на первый взгляд кажутся удобными. Не советовал бы использовать добавление слушателей через инспектор — при рефакторинге кода, или при банальном желании найти, кто подписан на события определенного объекта — поиск по коду вам ничего не даст, а в редакторе придется искать на всех сценах все инстансы исследуемого класса. Подписки через код — ок.
К сожалению, это вынужденная мера, если есть относительно продвинутые десигнеры, желающие собирать поведение и не желающие лезть в код.
Логическую часть — да. Но вот сделать меню с помощью Animator и UnityEvents невероятно удобно. Практически без единой строчки кода получается навигация с анимациями, что позволяет перенести работу по UI с программиста полностью на ГД, ТехАртиста или UI/UX-артиста.
Если удаление обрабатывающего событие объекта в обработчике мешает дальнейшей обработке — то давайте и не будем объект удалять в обработчике. Удалим его в сопрограмме, выполняющейся после обработки события — для чего движок, кстати, имеет стандартный метод. Будем удалять объект при помощи команды Destroy(this.gameObject, 0.0001). Удаление произойдёт, но не сразу, а будет отложено на 0.0001 секунды. Невооружённым глазом этой паузы не заметить, а вот процесс обработки события не запнётся на объекте и спокойно продолжится дальше.

Я не профи в юнити, но разве этот код не может сломаться если ОС решит переключить задачи в момент его исполнения, и 0.0001 секунда для юнити просто будет проглочена.

Что вы понимаете под "проглочена"?

Благодарю за статью. В свое время натыкался на события, но не стал использовать из-за того, что если хоть 1 объект уничтожится, не отписавшись от события, это может привести к багу, который придется долго и сложно искать. Если дойдут руки, вынесу на суд общественности свой велосипед, решающий эту проблему.
По поводу удаления объекта в обработчике событий — Вызов обработчиков происходит проходом циклом по их списку. Предположу, что проход осуществляется через Enumerator, и если объект из списка удаляется в цикле, то вызов MoveNext свалиться в ошибку. Если проход осуществляется через for, тогда событие будет вызвано только у нечетных (обращаемся к первому, удаляем его, второй становиться первым, обращаемся ко второму в текущем списке, это уже будет 3 элемент из начального списка, удаляем его, и т.д.).
Поэтому нельзя удалять в объекты в обработчике событий. К вашему методу я бы добавил, отключение элемента (gameObject.SetActive(false)) и изменение его родителя (transform.SetParent(...)).
У меня есть хорошая реализация системы ивентов. подписывайтесь сделаю статью.
На Хабре есть автор системы SMessages и его статья — хорошая альтернатива стандартным юнитевским эвентам.
А в чем преимущество перед нативными С# событиями? На первый взгляд функционал весь тот же самый: https://msdn.microsoft.com/en-us/library/awbftdfh.aspx.
В качестве преимуществ я вижу удобство интеграции с UI, возможность использования событий в JavaScript — там, насколько мне известно, адекватных альтернатив немного. Плюс возможность использования одних событий и JS, и C# кодом (события C# без костылей едва ли удастся удобно использовать по назначению из JavaScript), а также возможность настроить простейшие логические связи из дизайнера, а не через код. Последняя возможность, впрочем, сильно на любителя. Плюс, кому-то синтаксис UnityEvent-ов покажется удобнее событий C#, но это вопрос вкуса.
у меня показывает ошибку строчка
if (Input.anyKeyDown && testEvent!=null)
        {
            //testEvent.Invoke() ; // работает
            testEvent.Invoke(15);
        }

в C#.
кто нибудь подскажет, как в сишарпе передать параметр в эвент
Попробуйте вот так — может быть, у Вас что-то не так в объявлении класса для event-а, принимающего аргумент?
Sign up to leave a comment.

Articles