Понедельник, 12 Апреля 2021, 01:57

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 1
  • 1
Модератор форума: beril  
Форум игроделов » Движки для разработки игр и сложные системы разработки » Unity » Что то не так с системой корутин..
Что то не так с системой корутин..
killing002Дата: Вторник, 16 Марта 2021, 15:22 | Сообщение # 1
почетный гость
Сейчас нет на сайте
Приветствую всех.

Написал микро менеджер последовательных действий, через корутины. Хотя это даже менеджером нельзя назвать, но суть не в этом.
Ситуация такая -
Нпс при старте заполняет лист ienumerator'ов действиями которые он хочет последовательно производить(это как бы его цикл действий по уровню) и вызывает StartCoroutine (Это обертка на обычный запуск корутин, но перед этим он делает кое-что)
Код

countOfPoints = targets.Length;

        for (int i = 0; i < countOfPoints; i++)
        {
            nativeQueueEnumerators.Add(goToPoint(aipath, setter, targets[i]));
            nativeQueueEnumerators.Add(rotateToTarget(setter, targets[i]));
            nativeQueueEnumerators.Add(waitAFewMoment(setter, _waitingTime));
        }

        StartCoroutine(setter); // вызов функции

Тут происходит заполнение этого листа. Из названий методов, которые добавляются в очередь (в реальности же, эта очередь реализована листом), видно что происходит. Тут присутствует цикл, из-за того, что точек к которым нпс идет - несколько. То есть, нпс подошел -> повернулся в определенную сторону -> подождал и поновой, но только с другой точкой уже. Все эти действия реализованы через запуски корутин. То есть, каждое действие при окончании себя, вызывает следующее из очереди.

Код

   protected List<IEnumerator> nativeQueueEnumerators = new List<IEnumerator>();
   protected Queue<IEnumerator> queueEnumerators = new Queue<IEnumerator>();

queueEnumerators является очередью, с которым взаимодействую все действия. nativeQueueEnumerators это лист, который хранит все действия на которые подписался нпс изначально(при старте). Нужен он затем, что вызов происходит следующим образом:
Код


StartCoroutine(queueEnumerators.Dequeue());


То есть вызывается корутина, но при этом удаляется это действие из очереди, и в итоге при проходе одного цикла, то есть когда нпс пройдет все точки сделает все повороты и т.д, ему нужно вернуться в первую точку и начать все с начало, и для этого и нужен nativeQueueEnumerators, в очередь queueEnumerators, опять можно засунуть все те действия и опять начать цикл без нашего вмешательства. Надеюсь понятно объяснил, теперь к проблеме, а она заключается в следующем ->
Проблема в том, что первый цикл работает нормально, нпс проходит все точки и т.д, и когда приходит время возвращаться в начало, то есть происходит добавление всех начальных действий в queueEnumerators из nativeQueueEnumerators .
Код

   protected void MoveNext(AIDestinationSetter setter)
    {
        if (queueEnumerators.Count == 0) // произошел глобальный цикл
        {
            SetStartsValues();
        }

        Coroutine cor = setter.StartCoroutine(queueEnumerators.Dequeue());

        if (cor == null)
            Debug.Log("2 цикл не начинается по причине, что не запускается корутина ");
        
    }


Эта функция и запускает следующую корутину из очереди . Setter нужен, так как класс не наследует monobehavior, Условие cor == null, я вставил, что отследить, что происходит, и это условие активируется как после того, как queueEnumerators.Count станет равным нулю(условие выше), после чего произойдет SetStartsValues(),
Код

private void SetStartsValues()
    {
        for (int i = 0; i < nativeQueueEnumerators.Count; i++)
        {
            queueEnumerators.Enqueue(nativeQueueEnumerators[i]);
           
        }
    }


Дальше корутина не вызовется, не понятно почему, то есть cor будет равен null, в консоль выдаст это сообщение и выйдет из функции и нпс просто остановится и все. Фуу, надеюсь вам понятно. Так вот в чем вопрос, почему корутина не вызывается, он просто проходит по ней и выдает null и все.

Добавлено (17 Марта 2021, 11:26)
---------------------------------------------
Что то форум погибает по-моему, либо все знающие заняты делами. В общем решение предложили на другом ресурсе и оно работает. Кому интересно почему корутины не вызываются дважды, то вам сюда: cyberforum.ru


123

Сообщение отредактировал killing002 - Вторник, 16 Марта 2021, 15:26
drcrackДата: Среда, 17 Марта 2021, 12:09 | Сообщение # 2
старожил
Сейчас нет на сайте
Цитата
либо все знающие заняты делами.

люди не любят ковыряться в чужом коде, особенно когда его постят отдельными кусками пытаясь между ними обьяснить как это должно работать :D
killing002Дата: Среда, 17 Марта 2021, 18:02 | Сообщение # 3
почетный гость
Сейчас нет на сайте
А что, люди любят ковыраться в целых скриптах в 1к строк?

123
drcrackДата: Среда, 17 Марта 2021, 18:37 | Сообщение # 4
старожил
Сейчас нет на сайте
лучший вариант в таком случае — сделать отдельный скрипт с минимальным количеством строк для воспроизведения проблемы
maker-rusДата: Пятница, 19 Марта 2021, 20:44 | Сообщение # 5
Гений
Сейчас нет на сайте
Цитата killing002 ()
А что, люди любят ковыраться в целых скриптах в 1к строк?

Если у вас скрипты по 1к строк, то у меня для вас плохие новости. Хотя плохие новости начинаются еще с просмотра вашего кода.
Проблема изначально заключается в неверном выборе структуры хранения данных - очередь и итератор, при том, что из итератор используют как список, с хранением в нем объекта состояния, при том, что сама архитектура интератора работает только в одну сторону, тоже самое и с очередью (неверное использование структуры). Пошел посмотрел, что за решение было придумано и не удивился, что решением было не смена структуры хранения, а нагромаждения костылей. ;)
Цитата killing002 ()
Что то форум погибает по-моему, либо все знающие заняты делами. В общем решение предложили на другом ресурсе и оно работает. Кому интересно почему корутины не вызываются дважды, то вам сюда: ********

Могли бы просто процитировать сюда свое решение.


Сообщение отредактировал maker-rus - Пятница, 19 Марта 2021, 20:45
killing002Дата: Воскресенье, 21 Марта 2021, 15:35 | Сообщение # 6
почетный гость
Сейчас нет на сайте
Цитата maker-rus ()
Если у вас скрипты по 1к строк

Это гипербола, товарищ рэббит. Если вы не заметили диалог завелся в общем ключе, извольте не проецировать это на определенную душу.

По поводу новостей, прошу вас, оставьте их при себе).

Цитата maker-rus ()
что решением было не смена структуры хранения

И какая же "структура хранения данных" должна быть, позвольте узнать.

Цитата maker-rus ()
Могли бы просто процитировать сюда свое решение.

Поступать просто - мое табу


123

Сообщение отредактировал killing002 - Воскресенье, 21 Марта 2021, 15:43
BOOMДата: Вторник, 23 Марта 2021, 14:56 | Сообщение # 7
I am the creator of ADE
Сейчас нет на сайте
Подожди, а где у тебя прерывания корунтина командой yield?
Короче, как я понял, у тебя просто функция корунтина заканчивается и он, естественно, сборщиком тупо удаляется.
Советую сделать цикл в функции корунтина:

Код
for(int i=0; i<nativeQueueEnumerators.Count; i++)
{
    /* какие-то действия моба */
    yield return null; // на ЭТОМ месте будет прерываться корунтин и прокручивать весь код скриптов юнити.
}


И всё должно получиться.

Лучше познакомься с корунтинами. И вообще, думаю, тебе они в твоём случае не нужны. Я бы сделал скрипт, который бы инициализировался на каждом мобе. И функции передвижения запрятал бы в простом FixedUpdate - рассмотри этот вариант.


______________________________
Я вернулся, и это чудо.
______________________________
killing002Дата: Вторник, 23 Марта 2021, 17:58 | Сообщение # 8
почетный гость
Сейчас нет на сайте
Цитата BOOM ()
Подожди, а где у тебя прерывания корунтина командой yield?
Короче, как я понял, у тебя просто функция корунтина заканчивается и он, естественно, сборщиком тупо удаляется.

То есть ты считаешь, что у меня в корутинах нет yield.. Ты же понимаешь, что мне фреймворк не даст не прописать yield в Ienumerator.

Цитата BOOM ()
Советую сделать цикл в функции корунтина:

Не понял причем тут циклы..

Цитата BOOM ()
Лучше познакомься с корунтинами. И вообще, думаю, тебе они в твоём случае не нужны

А как ты предлагаешь еще реализовать выполнение последовательных действий нпс, если не брать в счет корутины и UniRx?

Цитата BOOM ()
И функции передвижения запрятал бы в простом FixedUpdate - рассмотри этот вариант.

Дело то не в самих методах..) А в выполнении последовательности методов .. Ты видимо не дочитал мои "объяснения, которые я запостил отдельными кусками"..))


123

Сообщение отредактировал killing002 - Вторник, 23 Марта 2021, 17:58
BOOMДата: Среда, 24 Марта 2021, 01:17 | Сообщение # 9
I am the creator of ADE
Сейчас нет на сайте
Я не считаю, что их нет. я считаю, что просто не правильно реализовано тело корутина, и твои слова доказывают мою догадку.

Цитата killing002 ()
Не понял причем тут циклы..


При том, что важен цикл в теле корунтина, особенно в твоём случае. Ведь тебе нужно последовательно выполнять действия юнита, а ты ещё используешь стероидную либу, где всё вокруг потоков то и построено. Как ты будешь организовывать ожидание с потока? Только через цикл.

В общем кратко, как я понял, логика будет выглядеть так:
1. Получить список действий.
2. Взять действие.
3. Выполнить действие.
4. Прогнать цикл системы (вызвать yield)
5. Смотрим, есть ли следующее действие: если есть, то возвращаемся к пункту 2. Если нет - Возвращаемся к 4 с целью ожидания действия или выходим.

Цитата killing002 ()
А как ты предлагаешь еще реализовать выполнение последовательных действий нпс, если не брать в счет корутины и UniRx?

Вот тут хочу поругаться конкретно. Если задаёшь вопрос, старайся как можно больше выкладывать кода, по которому задаёшь вопрос, и указывать, какие библиотеки ты используешь в своих проектах. Я не экстрасенс, чтобы знать, что у тебя экспортирована в проекте KakoChtoto стероидная либа. И тебе нравится всё, что связано с потоками и красивыми словами, что были когда-то, лет пять назад, написаны на хабре про неё.

P.S. Я не сторонник реактивного программирования и тем более UniRX.


______________________________
Я вернулся, и это чудо.
______________________________
maker-rusДата: Среда, 24 Марта 2021, 13:19 | Сообщение # 10
Гений
Сейчас нет на сайте
Цитата killing002 ()
Это гипербола, товарищ рэббит. Если вы не заметили диалог завелся в общем ключе, извольте не проецировать это на определенную душу.

В таком случае ответ товарищу Доктору, более, чем бессмысленный.

Цитата killing002 ()

Это гипербола, товарищ рэббит. Если вы не заметили диалог завелся в общем ключе, извольте не проецировать это на определенную душу.

По поводу новостей, прошу вас, оставьте их при себе).

Это устойчивое выражение, эти новости я и не собирался озвучивать, вы их и без меня должны понимать.

Цитата killing002 ()
И какая же "структура хранения данных" должна быть, позвольте узнать.

Ну уж точно не итератор, для того, что бы обеспечить последовательное выполнение действий объекта. Лучше бы прочитали книжки не про "асинхронное программирование" а.к.а "реактивное", которое в вашем случае не имеет смысла, так как прежде всего ориентировано на чистые функции (что это такое гуглите самостоятельно), а про алгоритмы и паттерны проектирования. Потому что исходя из вашего кода, из ООП, только названия.
Какую структуру данных я бы посоветовал? Обычные списки, в данном случае их было бы более, чем достаточно. В которые упаковать объект реализующий паттерн строитель, в котором и будут содержаться ваши: goToPoint, rotateToTarget, waitAFewMoment и соответственно вызываться функцией сборки, с возвращением нужных значений.
Цитата killing002 ()
Поступать просто - мое табу

Я заметил это по вашему коду, от этого и проблемы с производительностью, которую вы решили, что сможете решить через подключение библиотек, которые не понимаете как использовать. ^_^


Сообщение отредактировал maker-rus - Среда, 24 Марта 2021, 13:20
Форум игроделов » Движки для разработки игр и сложные системы разработки » Unity » Что то не так с системой корутин..
  • Страница 1 из 1
  • 1
Поиск:

Все права сохранены. GcUp.ru © 2008-2021 Рейтинг