Обмен сообщениями/событиями в приложении

Общие вопросы о Unity3D

Re: Обмен сообщениями/событиями в приложении

Сообщение Макс 03 июл 2013, 13:45

Johnson писал(а):Аналогично. Использую листы делегатов в словарях.
Я подозреваю, что все так делают, если разобрались с делегатами. Мессенджеры всегда и везде были медленной частью.

Я пол жизни привык вообще без ООП программировать, и вполне без него обходился. А теперь уже как-то не мыслю в этом направлении.
Немало почитал по теме, но всё кажется нелогичным каким-то, и неинтуитивно понятным. Так что никакие книги и руководства, тут не помогают...
Нужны практические примеры.
Макс
UNIверсал
 
Сообщения: 372
Зарегистрирован: 20 июн 2013, 23:05

Re: Обмен сообщениями/событиями в приложении

Сообщение seaman 03 июл 2013, 13:50

Так написали же уже выше ссылку на практический пример.
seaman
Адепт
 
Сообщения: 8352
Зарегистрирован: 24 янв 2011, 12:32
Откуда: Самара

Re: Обмен сообщениями/событиями в приложении

Сообщение Макс 03 июл 2013, 13:58

seaman писал(а):Так написали же уже выше ссылку на практический пример.


Ну это такой пример, который и так ясен был. правда я через Dictionary<string, Func<... делал.

Это в принципе ясно, но хотелось бы именно пример динамического добавления (или как там, подписывания делегатов) функций, например в тот же Update, когда нужно, и удаление, когда они уже ненужны.
Как из листа-то их все поочерёдно вызывать? Неужто цикл городить?
Макс
UNIверсал
 
Сообщения: 372
Зарегистрирован: 20 июн 2013, 23:05

Re: Обмен сообщениями/событиями в приложении

Сообщение temudjin 03 июл 2013, 14:04

Макс писал(а):
temudjin писал(а):
Макс писал(а):
Neodrop писал(а):использую листы делегатов, хранящиеся в словарике по ключу События.


Интересная тема... А можно примерчик такого рабочего паттерна, и его использования?


Вот он ценз избирательный в группу закрытую. А если без шуток все же ясно сказано.
Синтаксис:
Используется csharp
Dictionary <string, List<Action/*любой другой делегат*/>> singals;


Если этого не достаточно, и нужные еще какие то паттерны и пояснения - то нужно учить мат.часть.


Это занудство и дешовые понты!
думаешь, без тебя я таких "примеров" не понаходил в интернете?
Вот потому этот форум и загнивает, что прям никому вопрос уже задать нельзя, и получить вменяемый ответ.
Я более чем уверен, что это тебе нужно учиться. Еслиб ты хоть что-то мог и знал - тебе бы не составило труда, просто написать пример использования, а не твердить любимый штамп школьнегов-попугаев про мат часть.


дык что еще надо то понимать. Вменяемый ответ - это код на три страницы? Если ты не знаешь как оперировать структурами данных, считаешь кто то должен научить тебя? И если в сл. раз захочется обсудить что я могу и знаю пиши в личку =)
Аватара пользователя
temudjin
UNец
 
Сообщения: 15
Зарегистрирован: 17 ноя 2012, 01:48

Re: Обмен сообщениями/событиями в приложении

Сообщение Johnson 03 июл 2013, 14:06

Макс писал(а):
Johnson писал(а):Аналогично. Использую листы делегатов в словарях.
Я подозреваю, что все так делают, если разобрались с делегатами. Мессенджеры всегда и везде были медленной частью.

Я пол жизни привык вообще без ООП программировать, и вполне без него обходился. А теперь уже как-то не мыслю в этом направлении.
Немало почитал по теме, но всё кажется нелогичным каким-то, и неинтуитивно понятным. Так что никакие книги и руководства, тут не помогают...
Нужны практические примеры.


Ну, я лично долго писал процедурные программы (для микроконтроллеров), и на ООП перелез буквально за месяц. Сейчас процедурные кажутся ну очень неказистыми.

а пример простейший (написан с коленки):
Синтаксис:
Используется csharp
public class SomeController : MonoBehaviour{
        // Пусть он будет синглтоном, но синглтон холдер не буду объявлять, не за этим пишу. Получение инстанса: GetInstance();

        public delegate void OnSomeEvent(int someValue);

        private readonly Dictionary<string,List<OnSomeEvent>> _listeners = new Dictionary<string, List<OnSomeEvent>>();

        public void AddListener(string eventType, OnSomeEvent ev){
                List<OnSomeEvent> l;
                if (!_listeners.containsKey(eventType)){
                        _listeners.Add(eventType, l = new List<OnSomeEvent>());
                } else {
                        l = _listeners[eventType];
                }
                l.Add(ev);
        }
        public void RemoveListener(string eventType, OnSomeEvent ev){
                if (!_listeners.containsKey(eventType)){
                        return;
                } else {
                        _listeners[eventType].Remove(ev);
                }
        }
        public void FireListeners(string eventType, int value){
                foreach(OnSomeEvent:ev in _listeners[eventType]){
                        if (ev != null){
                                ev(value);
                        }
                }
        }

        void Update(){
                // ... some code
                if (someBool){
                        FireListeners("MyEvent", 1);
                }
        }
}

// откуда-то из кода:
private void ListenSomeController(){
        SomeController.GetInstance().AddListener("MyEvent", OnMyEvent);
}

private void OnMyEvent(int value){
        Debug.Log("MyEvent:"+value);
}
 


Разумеется, в делегатах можно использовать возвратное значение, или не использовать аргументы (public delegate string OnSomeEvent()).
Johnson появился в результате деления на null. Кривокодер-рецидивист. Кусается.
Хорошо, что в больнице хирурги не такие же, как новички на этом форуме. Пришел вытащить гвоздь из руки, а они яйца оттяпали...
ProgrammerNotFoundException on line 0!
Аватара пользователя
Johnson
UNIверсал
 
Сообщения: 447
Зарегистрирован: 09 июн 2013, 16:31
Откуда: Пермь
Skype: Johnson1893
  • Сайт
  • ICQ

Re: Обмен сообщениями/событиями в приложении

Сообщение broken 03 июл 2013, 14:13

Вот здесь более модифицированный пример:
http://wiki.unity3d.com/index.php/Advanced_CSharp_Messenger
Проекты на Unity3D:
Монополия 3D: http://unity3d.ru/distribution/viewtopic.php?f=10&t=25816
Битва валют 3D (файтинг): http://unity3d.ru/distribution/viewtopic.php?f=17&t=17186
Аватара пользователя
broken
UNITрон
 
Сообщения: 243
Зарегистрирован: 29 мар 2013, 15:00
Откуда: Набережные Челны, Россия
Skype: al.ryazanov

Re: Обмен сообщениями/событиями в приложении

Сообщение Макс 03 июл 2013, 14:17

Johnson, спасибо! Сразу видно, человек практикой занимается, а не просто теоретик, как некоторые... :)
Ух правда и накручено тут... Это правда работает быстрее чем через простое суммирование делегатов?
Размеры кода внушительно отличаются...
Макс
UNIверсал
 
Сообщения: 372
Зарегистрирован: 20 июн 2013, 23:05

Re: Обмен сообщениями/событиями в приложении

Сообщение Johnson 03 июл 2013, 14:18

broken писал(а):Вот здесь более модифицированный пример:
http://wiki.unity3d.com/index.php/Advanced_CSharp_Messenger

Ну, если нужен более гибкий и громоздкий функционал, чем простое добавление/удаление/поповещение - то пожалуйста, пользуйтесь готовым решением, в логику которого нужно долго вникать.

Я описал общий пример системы оповещения, если один класс может генерировать несколько ивентов.
Обычно же (если 1-2 ивента класс генерирует) я применяю оповещения даже без словаря - просто лист делегатов.
Тогда и форич не нужен в оповещателе, и вообще работает пошустрее.

Не забывайте, что чем проще и быстрее код - тем он меньше скажется на фпс. Плюс, если код простой - то вы лучше его понимаете. Не знаю, как остальные, но я до коликов в животе терпеть не могу "черные ящики". Если уж и приходится использовать сторонее решение - то стараюсь понять как оно устроено.
Johnson появился в результате деления на null. Кривокодер-рецидивист. Кусается.
Хорошо, что в больнице хирурги не такие же, как новички на этом форуме. Пришел вытащить гвоздь из руки, а они яйца оттяпали...
ProgrammerNotFoundException on line 0!
Аватара пользователя
Johnson
UNIверсал
 
Сообщения: 447
Зарегистрирован: 09 июн 2013, 16:31
Откуда: Пермь
Skype: Johnson1893
  • Сайт
  • ICQ

Re: Обмен сообщениями/событиями в приложении

Сообщение Johnson 03 июл 2013, 14:22

Макс писал(а):Johnson, спасибо! Сразу видно, человек практикой занимается, а не просто теоретик, как некоторые... :)
Ух правда и накручено тут... Это правда работает быстрее чем через простое суммирование делегатов?
Размеры кода внушительно отличаются...


Насчет различия со скоростью мультиделегатов не скажу - не знаю и не проверял.
Я тут пару дней назад давал ссылочку на описание делегатов на MSDN, там они подробно описаны. Теоретически, мультиделегат использует такой же лист, раз у него перегружены операторы добавления и вычитания...
Но, раз умные люди говорят, что словарь листов делегатов на много быстрее, чем мультиделегирование - полагаю, что так и есть.
А не использую я мультиделегирование по простой причине - не люблю :)

PS: не знаю, чего тут накручено)) Практически процедурное программирование :) Вот в сетевом движке у меня накручено - сам пугаюсь (3 очереди, 2 пула потоков, 3 демон-потока, и прочие вкусности), да руки не доходят отрефакторить...
Johnson появился в результате деления на null. Кривокодер-рецидивист. Кусается.
Хорошо, что в больнице хирурги не такие же, как новички на этом форуме. Пришел вытащить гвоздь из руки, а они яйца оттяпали...
ProgrammerNotFoundException on line 0!
Аватара пользователя
Johnson
UNIверсал
 
Сообщения: 447
Зарегистрирован: 09 июн 2013, 16:31
Откуда: Пермь
Skype: Johnson1893
  • Сайт
  • ICQ

Re: Обмен сообщениями/событиями в приложении

Сообщение Макс 03 июл 2013, 14:30

Johnson писал(а):Не забывайте, что чем проще и быстрее код - тем он меньше скажется на фпс. Плюс, если код простой - то вы лучше его понимаете. Не знаю, как остальные, но я до коликов в животе терпеть не могу "черные ящики". Если уж и приходится использовать сторонее решение - то стараюсь понять как оно устроено.


Тоже не люблю чёрные ящики. Но чтобы создать своё, нужно понять разные способы, как делают другие, и выбрать лучший.
Вот очень заинтересовало, как сделал Neodrop.
А более простой код, я уже использовал до этого, но Neodrop его что-то раскритиковал, как я понимаю...

Куда уж проще-то?
Синтаксис:
Используется csharp
public delegate void Delegat();
Delegat d;

d = mainFunc1;//добавляем делегату первый метод    
d += mainFunc2;//добавляем второй метод    
d += mainFunc3;//добавляем третий метод

//методы, на которые ссылается делегат:
void mainFunc1(){

        Debug.Log(1);  
}
       
void mainFunc2(){
               
        Debug.Log(2);  
}      
       
void mainFunc3(){
               
        Debug.Log(3);  
}



//Выполняем последовательно, все назначеные делегату методы:
if(d != null) d(); //вызов делегата



d -= mainFunc2;// Можем удалить этот метод у делегата

d = null;//Или удалить все методы делегата
Макс
UNIверсал
 
Сообщения: 372
Зарегистрирован: 20 июн 2013, 23:05

Re: Обмен сообщениями/событиями в приложении

Сообщение Johnson 03 июл 2013, 14:34

Макс писал(а):
Johnson писал(а):Не забывайте, что чем проще и быстрее код - тем он меньше скажется на фпс. Плюс, если код простой - то вы лучше его понимаете. Не знаю, как остальные, но я до коликов в животе терпеть не могу "черные ящики". Если уж и приходится использовать сторонее решение - то стараюсь понять как оно устроено.


Тоже не люблю чёрные ящики. Но чтобы создать своё, нужно понять разные способы, как делают другие, и выбрать лучший.
Вот очень заинтересовало, как сделал Neodrop.
А более простой код, я уже использовал до этого, но Neodrop его что-то раскритиковал, как я понимаю...

Куда уж проще-то?
Синтаксис:
Используется csharp
public delegate void Delegat();
Delegat d;

d = mainFunc1;//добавляем делегату первый метод    
d += mainFunc2;//добавляем второй метод    
d += mainFunc3;//добавляем третий метод

//методы, на которые ссылается делегат:
void mainFunc1(){

        Debug.Log(1);  
}
       
void mainFunc2(){
               
        Debug.Log(2);  
}      
       
void mainFunc3(){
               
        Debug.Log(3);  
}



//Выполняем последовательно, все назначеные делегату методы:
if(d != null) d(); //вызов делегата



d -= mainFunc2;// Можем удалить этот метод у делегата

d = null;//Или удалить все методы делегата


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

Ах, да! если прототип делегата имеет вид, отличный от простого (public delegate void OnEvent();) - то ждите проблем с передачей аргументов или получением результатов :) Там довольно нелогично сделано - надо перебирать инвокации в мультиделегатах. Поищите ссылку, которую я показывал - там довольно просто расписано про это.

PS: Про "черные тяжелые ящики" мне проще и приятнее было написать http сервер на джаве, чем использовать тяжелый tomcat, у которого я не использовал бы и половины возможностей...
Johnson появился в результате деления на null. Кривокодер-рецидивист. Кусается.
Хорошо, что в больнице хирурги не такие же, как новички на этом форуме. Пришел вытащить гвоздь из руки, а они яйца оттяпали...
ProgrammerNotFoundException on line 0!
Аватара пользователя
Johnson
UNIверсал
 
Сообщения: 447
Зарегистрирован: 09 июн 2013, 16:31
Откуда: Пермь
Skype: Johnson1893
  • Сайт
  • ICQ

Re: Обмен сообщениями/событиями в приложении

Сообщение Макс 03 июл 2013, 14:41

Johnson писал(а):Ах, да! если прототип делегата имеет вид, отличный от простого (public delegate void OnEvent();) - то ждите проблем с передачей аргументов или получением результатов :) Там довольно нелогично сделано - надо перебирать инвокации в мультиделегатах. Поищите ссылку, которую я показывал - там довольно просто расписано про это.

Спасибо, поищу. Но пока что, вопрос так и не стоит.
Пока что задача лишь в том, чтобы в Update находилось и выполнялось, как можно меньше операторов и функций, и чтобы методы как бы временно инкапсулировались в Update, и за ненадобностью оттуда удалялись.
Макс
UNIверсал
 
Сообщения: 372
Зарегистрирован: 20 июн 2013, 23:05

Re: Обмен сообщениями/событиями в приложении

Сообщение Johnson 03 июл 2013, 14:46

Макс писал(а):
Johnson писал(а):Ах, да! если прототип делегата имеет вид, отличный от простого (public delegate void OnEvent();) - то ждите проблем с передачей аргументов или получением результатов :) Там довольно нелогично сделано - надо перебирать инвокации в мультиделегатах. Поищите ссылку, которую я показывал - там довольно просто расписано про это.

Спасибо, поищу. Но пока что, вопрос так и не стоит.
Пока что задача лишь в том, чтобы в Update находилось и выполнялось, как можно меньше операторов и функций, и чтобы методы как бы временно инкапсулировались в Update, и за ненадобностью оттуда удалялись.


Извиняюсь, наврал. Не в MSDN, а в RSDN.

Делегаты не помогут сделать меньше вызовов из апдейта.
Если что-то тяжелое - обрабатывайте это в корутине (если необходимо выполнять от имени основного потока), либо можно использовать отдельный поток + очередь делегатов (в блоке delegate{} можно даже передавать код прямиком, а не через функции). В апдейте помещаете делегат в очередь, в потоке по исполнению очередного делегата цикл, который ждет появления в очереди делегата, dequeue его (не знаю, как перевести одним словом), и исполняет.
Johnson появился в результате деления на null. Кривокодер-рецидивист. Кусается.
Хорошо, что в больнице хирурги не такие же, как новички на этом форуме. Пришел вытащить гвоздь из руки, а они яйца оттяпали...
ProgrammerNotFoundException on line 0!
Аватара пользователя
Johnson
UNIверсал
 
Сообщения: 447
Зарегистрирован: 09 июн 2013, 16:31
Откуда: Пермь
Skype: Johnson1893
  • Сайт
  • ICQ

Re: Обмен сообщениями/событиями в приложении

Сообщение Макс 03 июл 2013, 14:59

Johnson писал(а):Делегаты не помогут сделать меньше вызовов из апдейта.


Ну как же не помогут?
Когда вместо:
Синтаксис:
Используется csharp
void Update(){

    if(условие) mainFunc1();
    if(условие) mainFunc2();
    if(условие) mainFunc3();
    if(условие) mainFunc4();
    if(условие) mainFunc5();
    if(условие) mainFunc6();
    if(условие) mainFunc7();
    if(условие) mainFunc8();
    if(условие) mainFunc9();
    if(условие) mainFunc10);
     ...
    if(условие) mainFunc100500();
}


Будет всего лишь:
Синтаксис:
Используется csharp
void Update(){

    if(d != null) d();

}


Да к тому же, вся эта череда проверок, будет висеть и обрабатываться в Update всегда,
А очередь делегатов - она динамичная, в ней будут находиться лишь необходимые в данный момент вызовы методов.
Ведь никому ненужно сразу вызывать все 100500 методов! Вызывают время от времени некоторые из них, а некоторые выполняются регулярно, но иногда их можно и не выполнять.
Макс
UNIверсал
 
Сообщения: 372
Зарегистрирован: 20 июн 2013, 23:05

Re: Обмен сообщениями/событиями в приложении

Сообщение Johnson 03 июл 2013, 15:49

Эмм. Ты либо не совсем понимаешь принципы программирования, либо не совсем понимаешь принципы делегирования.

Если ты эти циклы вынесешь куда-то ещё, а из апдейта будешь вызывать метод или делегат того места, куда перенес - то код от этого быстрее не станет, можно сказать он наоборот, станет несколько медленнее.
Вызовы методов тоже занимают несколько тактов процессорного времени, а уж делегаты - и подавно, они часть довольно медленной системы отражений.
Нужно понимать, что поток он как нить (иногда так и переводят слово Thread). Он следует по коду строчка за строчкой. Если ты куда-то унес свой код и вызываешь это место (функцию) - то нить проследует в эту функцию, так же точно выполнит там свой код и вернется обратно, продолжив "путь".

Вообще, вызов метода на прямую, или вызов делегата - практически одно и то же действие. Преимущество только в том, что у классе, генерирующим ивенты не надо обращаться к другому классу (закон Деметры), а вот слушатель сам указывает такому классу что нужно его оповестить о событии (вызов делегата аналогичен вызову SomeOtherClass.GetInstance().OnMyEvent(valie);).
Johnson появился в результате деления на null. Кривокодер-рецидивист. Кусается.
Хорошо, что в больнице хирурги не такие же, как новички на этом форуме. Пришел вытащить гвоздь из руки, а они яйца оттяпали...
ProgrammerNotFoundException on line 0!
Аватара пользователя
Johnson
UNIверсал
 
Сообщения: 447
Зарегистрирован: 09 июн 2013, 16:31
Откуда: Пермь
Skype: Johnson1893
  • Сайт
  • ICQ

Пред.След.

Вернуться в Общие вопросы

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 10