Комментарии 18
Попробуйте передавать в качестве параметра MarshalByValue тип (для этого придется сделать наследника UnityEvent с нужным типом) — будет гарантированный GC allocation. Ну и «EventBusTest» как пример использования простой шины событий. По поводу «невозможности использования C# кода в JS» — нужно положить C# код в папочки первого этапа компилирования (Standard Assets, Plugins, etc) — тогда этот код станет доступным в JS.
0
И не получается. Удаляется только самый первый (иногда — два) из принимающих событие объектов, а до остальных почему-то после этого событие уже не доходит. Странно? Странно и необъяснимо. Может быть, кто-то из гуру Unity подскажет мне идеологически правильный подход, но поскольку я люблю придумывать велосипеды пока на обнаружил более элегантное решение, то поделюсь, опять же, своим.
Популярная "особенность" подобных систем. Удаление объекта же приводит к отписыванию от события (вы реализовали это прошлом пункте), верно? Таким образом, внутренняя коллекция обработчиков изменяется в процессе ее обхода. А большинство коллекций на такое не рассчитаны.
К примеру, если там внутри связный список — то удаление в процессе обхода текущего элемента обычно приводит к тому, что обход списка останавливается (если нет специальной реализации этого случая).
+1
Второй экземпляр просто некуда оказывается вписать — поле принимающего сигнал объекта не предусматривает множественности записей.
На вашей же картинке:
Написано "List is Empty", и кнопочки "±" намекают на то, что можно добавить несколько получателей мышкой.
+5
Все эти Юнитевые «штучки» только на первый взгляд кажутся удобными. Не советовал бы использовать добавление слушателей через инспектор — при рефакторинге кода, или при банальном желании найти, кто подписан на события определенного объекта — поиск по коду вам ничего не даст, а в редакторе придется искать на всех сценах все инстансы исследуемого класса. Подписки через код — ок.
+2
К сожалению, это вынужденная мера, если есть относительно продвинутые десигнеры, желающие собирать поведение и не желающие лезть в код.
+1
Логическую часть — да. Но вот сделать меню с помощью Animator и UnityEvents невероятно удобно. Практически без единой строчки кода получается навигация с анимациями, что позволяет перенести работу по UI с программиста полностью на ГД, ТехАртиста или UI/UX-артиста.
0
Если удаление обрабатывающего событие объекта в обработчике мешает дальнейшей обработке — то давайте и не будем объект удалять в обработчике. Удалим его в сопрограмме, выполняющейся после обработки события — для чего движок, кстати, имеет стандартный метод. Будем удалять объект при помощи команды Destroy(this.gameObject, 0.0001). Удаление произойдёт, но не сразу, а будет отложено на 0.0001 секунды. Невооружённым глазом этой паузы не заметить, а вот процесс обработки события не запнётся на объекте и спокойно продолжится дальше.
Я не профи в юнити, но разве этот код не может сломаться если ОС решит переключить задачи в момент его исполнения, и 0.0001 секунда для юнити просто будет проглочена.
0
Что вы понимаете под "проглочена"?
0
Нужно просто в момент вызова эвента собирать подписчиков в отдельный лист и крутить в нем — это позволит модифицировать коллекцию подписки без дополнительных костылей.
+1
Благодарю за статью. В свое время натыкался на события, но не стал использовать из-за того, что если хоть 1 объект уничтожится, не отписавшись от события, это может привести к багу, который придется долго и сложно искать. Если дойдут руки, вынесу на суд общественности свой велосипед, решающий эту проблему.
0
По поводу удаления объекта в обработчике событий — Вызов обработчиков происходит проходом циклом по их списку. Предположу, что проход осуществляется через Enumerator, и если объект из списка удаляется в цикле, то вызов MoveNext свалиться в ошибку. Если проход осуществляется через for, тогда событие будет вызвано только у нечетных (обращаемся к первому, удаляем его, второй становиться первым, обращаемся ко второму в текущем списке, это уже будет 3 элемент из начального списка, удаляем его, и т.д.).
Поэтому нельзя удалять в объекты в обработчике событий. К вашему методу я бы добавил, отключение элемента (gameObject.SetActive(false)) и изменение его родителя (transform.SetParent(...)).
Поэтому нельзя удалять в объекты в обработчике событий. К вашему методу я бы добавил, отключение элемента (gameObject.SetActive(false)) и изменение его родителя (transform.SetParent(...)).
0
У меня есть хорошая реализация системы ивентов. подписывайтесь сделаю статью.
-4
На Хабре есть автор системы SMessages и его статья — хорошая альтернатива стандартным юнитевским эвентам.
0
А в чем преимущество перед нативными С# событиями? На первый взгляд функционал весь тот же самый: https://msdn.microsoft.com/en-us/library/awbftdfh.aspx.
0
В качестве преимуществ я вижу удобство интеграции с UI, возможность использования событий в JavaScript — там, насколько мне известно, адекватных альтернатив немного. Плюс возможность использования одних событий и JS, и C# кодом (события C# без костылей едва ли удастся удобно использовать по назначению из JavaScript), а также возможность настроить простейшие логические связи из дизайнера, а не через код. Последняя возможность, впрочем, сильно на любителя. Плюс, кому-то синтаксис UnityEvent-ов покажется удобнее событий C#, но это вопрос вкуса.
0
у меня показывает ошибку строчка
в C#.
кто нибудь подскажет, как в сишарпе передать параметр в эвент
if (Input.anyKeyDown && testEvent!=null)
{
//testEvent.Invoke() ; // работает
testEvent.Invoke(15);
}
в C#.
кто нибудь подскажет, как в сишарпе передать параметр в эвент
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Забытое секретное оружие Unity — UnityEvents