Деревья поведения и отмена запущенных событий

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

Предположим следующее простое дерево:

Tree
  while "talk_to_lady"
    sequence
      move_to_position
      talk
  while "dance"
    sequence
      dance_move_1
      dance_move_2

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

Предположим, что танец верен, персонаж танцует, и это нормально. Теперь talk_to_lady имеет значение true, что означает, что персонаж должен пойти туда и поговорить с ней. Хотя эта задача имеет более высокий приоритет, и я действительно хочу, чтобы это произошло, я все же хочу, чтобы персонаж закончил текущий танцевальный узел (т. не хочется ждать).

Мое решение состояло бы в том, чтобы дерево вызывало, скажем, метод Abort() для действия dance_move, но если это возвращает состояние выполнения, оно будет игнорировать действие talk до тех пор, пока действие dance_move не вернет успех или неудачу. Кроме того, если событие с более высоким приоритетом в дереве является другим действием, а не узлом while, возможно, оно уже произвело изменения состояния, которые могут помешать действию dance_move.

Я что-то упустил или есть решение, о котором я не читал?


person cboe    schedule 11.08.2018    source источник
comment
Не уверен, правильно ли я понимаю - не будет ли текущий код заканчивать последовательность dance перед переходом к последовательности talk_to_lady? Или вы спрашиваете, как прервать/продолжить в зависимости от ситуации?   -  person iamanigeeit    schedule 20.08.2018
comment
Я бы представил решение как очередь или стек, содержащий список оставшихся действий, которые необходимо выполнить.   -  person iamanigeeit    schedule 20.08.2018
comment
На каком языке должен быть написан ваш код? Подход может отличаться   -  person Milan Velebit    schedule 20.08.2018
comment
Извините за поздний ответ - насколько я понимаю, эти последовательности всегда проверяются от начала до конца, поэтому, если первый возвращает успех, пока работает второй, он прервет второй, что не обязательно то, что я хочу . Я пишу на С#   -  person cboe    schedule 22.08.2018


Ответы (2)


IMO, вам понадобится другая, отдельная функция listener, которая будет координировать выполнение других функций или запускать каждую функцию в своем собственном потоке, игнорируя «синхронный» механизм, вызывающий проблему. . Теперь, в зависимости от используемого языка, это может быть очень тривиально или очень нетривиально. Используя подход многопоточности, я бы установил функции, которые будут выполняться в соответствующих потоках, что позволит вам останавливать потоки по вашему желанию из основного потока, который на самом деле будет вашим прослушивателем/порождающим событием. У вас может быть вспомогательный класс, который будет создан в вашем основном потоке, скажем, ThreadManager или что-то в этом роде, в котором будут вложены методы и объекты/массивы для управления запущенными потоками (ваши функции).

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

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

person Milan Velebit    schedule 20.08.2018
comment
Спасибо, мне нравится ваше мышление, но я боюсь, что многопоточность не вариант, и я хочу, чтобы это было просто. Кроме того, моя проблема на самом деле не в том, как остановить действие, когда запускается событие с более высоким приоритетом, а в том, как предотвратить это, пока текущее действие не завершено. - person cboe; 22.08.2018
comment
А, теперь я вижу, что неправильно понял, что вы на самом деле хотите сохранить своего рода синхронность. Я бы все же сказал, что это один из самых жизнеспособных вариантов. Я немного отредактировал свой вопрос. Видя, что вы используете C#, вы можете повозиться с использованием async/await, но это в определенной степени, я бы все же сказал, что используйте многопоточность, но я рад видеть, что предлагают другие, отмеченные звездочкой. - person Milan Velebit; 22.08.2018

вы можете добавить узел условия поверх talk_to_lady. узел условия в качестве декоратора обеспечивает условие, которое завершает только танец, а затем выполняет поведение разговора с дамой.

Tree
  condition: "dance state" == "finish" 
    while "talk_to_lady"
      sequence
        move_to_position
        talk
  while "dance"
    sequence
      dance_move_1
      dance_move_2
person Sunny Sun    schedule 29.10.2020