Скриптинг И.И.: Дерево выбора поведения

Материал из CryWiki Russia

Перейти к: навигация, поиск
О статье
АвторAndreyFilantrop
СложностьСредняя
ТребованияТекстовый редактор, Crysis 2 Mod SDK.
Дата добавления20/07/12


Содержание

Дерево выбора поведения

Обзор

В то время как скрипты поведения представляют собой индивидуальную логическую обработку состояний в которых может находиться ИИ, по прежнему должна существовать возможность выбора между ними, чтобы выбрать правильное поведение в любой момент игры. Дерево выбора поведений (BHS) определяет набор правил, которые позволяют ИИ системе сохранять необходимое поведение ИИ всё время. Каждый ИИ-тип должен быть связан с BHS, и более чем один ИИ-тип может относиться к тому же BHS.

Давайте определим некий пример, на который в дальнейшем мы будем ссылаться в течение всей этой статьи. Скажем некий ИИ, которого мы назовем «Grunt», имеет 3 поведения: idle, alert, и attack. (перевод этих названий соответственно: в режиме ожидания - т.е. дефолтное поведение, встревоженный, боевое поведение). ИИ должен быть по определению в дефолтном поведении idle, когда он не получает внешних стимулов; в состоянии alert он должен находиться, года он слышит что-то неизвестное, и наконец в состояние attack он перейдет, когда он визуально может уже видеть врага. Обратно в состояние idle он может перейти через некоторое время, если он на его протяжении не получает обновляющихся слуховых/визуальных стимулов. Чтобы поддерживать такую систему, ИИ должен иметь Дерево Выбора Поведений или BHS, которое будет определять, какие условия ассоциируются с каким из поведений. Глобальная ИИ-система будет заботиться об обновлении ИИ перцепции (т.е. восприятии сигналов) и посылании сигналов событий, когда состояние перцепции ИИ меняется.

Этот макет является ключом к функционированию ИИ в игре, т.к. он определяет все поведения, которые ИИ должен поддерживать в игре. Это, естественно, должно переводиться в BHS с набором для реализации подходящего поведения. Все BHS должны быть определены внутри папки «Game» в директории «Scripts/AI/SelectionTrees». Новое дерево, добавляемое в эту папку, будет автоматически проявлено в игре при перезагрузке ИИ или при перезагрузке игры. Чтобы связать BHS с конкретным архетипом ИИ, загрузите архетип в редакторе, и используйте выпадающее меню для BehaviorSelectionTree параметра под вкладкой Class Properties.

Дерево Выбора Поведений: концепция и анатомия

BHS концепция предполагает, что в любой момент времени ИИ будет иметь одно поведение соответствующее текущему состоянию. Так, когда ИИ слышит какой-то звук, он начинает исследовать его, а когда видит врага - атакует его. Обратите внимание, что BHS не содержит информации о том, как ИИ переходит между состояниями, но содержит - только о том, как выбрать правильно поведение для правильного момента. BHS определяется посредством XML скрипт-файла и должно быть пригодным для ИИ, чтобы он мог перейти в любое поведение. Если BHS недоступно, то ИИ может только поворачивать голову по направлению к цели, и «ai_debugdraw 1» будет показывать «No Behavior» в дебаге.

BHS XML файлы не содержат никакой скриптовой логики и являются чисто файлами данных, которые ИИ система рассматривает, когда решает, в каком поведении ИИ должен находиться в конкретный период времени. BHS также могут включать заменяемые блоки, позволяющие дизайнеру распределять базовое поведение между множеством ИИ.

Дерево Выбора Поведений содержит 4 компонента:

1) Selection Variables (Выбираемые переменные): Переменные используются для определения условий, которые выбирают между статусами в Дереве.

2) Signal Variables (Сигнальные переменные): Сигналы, как посылаемые ИИ системой, которые непосредственно изменяют состояние выбираемых переменных (см.пункт №1).

3) Leaf Translations (Листы трансляции): Список отображения от общих имен до архетип-специфических имен поведений.

4) The Selection Tree (Дерево выбора): структура дерева, которая определяет, какие поведения являются приоритетными и какие условия должны быть выполнены.

Selection Variables:

Selection variables объявлены в своем собственном ​​разделе под названием «Переменные». Каждая переменная является всего лишь именно декларацией, представляющей булево значение (т.е. логическое) true (правда) или false (ложь). Они могут быть включены/выключены извне как ИИ-системой, так и самими поведениями. Они являются концептуальными переключателями, которые необходимы чтобы выбирать текущее состояние поведения ИИ, использующего данное BHS. Кроме того, возможно передавать значение по умолчанию (хотя по умолчанию все значения установлены на положение «ложь»).

Чтобы проиллюстрировать вышеизложенное, секция selection variable может выглядеть таким образом:

<Variables>
  <Variable name="AwareOfSound" default="false"/>
  <Variable name="AwareOfEnemy"/>
</Variables>

Signal Variables:

Signal Variables представляют возможность напрямую изменять переменные в ИИ BHS. Они приходят из ИИ системы и включают/выключают переменные объявленные в секции под названием «Переменные». Три параметра должны быть определены для каждой сигнальной переменной. Должны быть определены имя, которое подходит под имя ожидаемого сигнала из ИИ системы, имя selection variable, которое должно быть изменено, значение, в которое устанавливается selection variable.

Чтобы проиллюстрировать вышеизложенное, секция signal variable может выглядеть таким образом:

<SignalVariables>
  <Signal name="OnHearSound" variable="AwareOfSound" value="true"/>
  <Signal name="OnEnemySeen" variable="AwareOfEnemy" value="true"/>
  <Signal name="OnNoTarget" variable="AwareOfSound" value="false"/>
  <Signal name="OnNoTarget" variable="AwareOfEnemy" value="false"/>
</SignalVariables>

Leaf Translations:

Leaf Translations нужны для более ясного и более здравого определения дерева. Они обеспечивают перенесение общих имен поведений (которые обычно распределяются по ИИ) в архетип-специфические поведения. Это не является необходимым, если используется общедоступный (общий) BHS блок выбора, который будет обсуждаться в дальнейшем в данном документе. Хотя, они могут быть использованы, чтобы придать вашему дереву выбора более удобочитаемый облик.

Чтобы проиллюстрировать вышеизложенное, секция leaf translations может выглядеть таким образом:

<LeafTranslations>
  <Map node="Idle" target="GruntIdle"/>
  <Map node="Investigate" target="GruntInvestigate"/>
  <Map node="Attack" target="GruntAttack"/>
</LeafTranslations>

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

Selection tree

Эта секция использует 3 вышеописанные компонента, чтобы определить доступные поведения для ИИ, и определяет, как откорректировать выбранные каждый раз, когда дерево оценивается (читается) заново. В порядке предложения их по имени, поведения организованы в структуру дерева. Каждый узел дерева представляет группировку поведений и условий, необходимых чтобы позволить читать дочерние узлы. Каждый leaf узел представляет ссылку на специфическое поведение и условия «condition», необходимое, чтобы пройти к нему, чтобы соответственно быть выбранным.

Приоритет узлов определяется порядком в файле. Так, если два или более узлов будут подходить под текущее состояние selection variable, то первый встреченный по списку расположения в дереве будет выбран.

Чтобы проиллюстрировать вышеизложенное, секция selection tree может выглядеть таким образом:

<Priority name="Root">
  <Priority name="Combat" condition="AwareOfEnemy">
    <Leaf name="Attack"/>
  </Priority>
  <Leaf name="Investigate" condition="AwareOfSound"/>
  <Leaf name="Idle"/>
</Priority>

Есть несколько примечательных вещей, на которые следует обратить внимание, исходя из вышеописанных примеров. Имена листьев leaf должны соответствовать именам поведений. Либо необработанному имени поведения (GruntAttack), либо уже нанесенному имени (Attack). В примере обратите внимание, что «Attack» является листом для группировки поведения, называемой «Combat». Она имеет только один лист, но большее количество может быть добавлено позже. Для оценки любого из этих листьев, selection variable переменная «AwareOfEnemy» должна быть true. Т.к. «Attack» находится выше в структуре файла, если он проходит по условиям, то он будет выбран, даже если «Investigate» тоже доступен. И последнее что надо упомянуть, то что «Idle» поведение не имеет каких-то прикрепленных к нему условий. Сей факт делает его дефолтным поведением. Если в данный момент больше ничего не оценивается, чтобы быть действующим первее, то «Idle» будет выбрано.

Не существует лимита переменных, нанесений на дефольное поведение, записей в поведении, которые могут быть определены в BHS.

Оценка Дерева Выбора Поведений

Хорошее понимание того, как BHS оценивается поможет в понимании того, каким образом лучше создавать как поведения, так и само BHS. Как поведения, так и BHS не копируется для каждого клона ИИ, который его использует. Вместо этого каждый клон ИИ получает копию selection variables, которая полностью отражает выбранный статус ИИ. Дерево затем оценивается набором selection variables, чтобы определить, какой статус соответствующий ИИ должен получить.


При каждом ИИ-обновлении в рамках ИИ системы (много фреймов в секунду):

  • Дерево ИИ переоценивает ИИ-ассоциированные Selection Variables.
  • Если выбранное поведение является тем же, что и текущее, то ничего не происходит.
  • Если выбранное поведение другое, тогда ИИ вызывает destructor текущего поведения.
  • ИИ переходит в новое поведение и...
  • Constructor нового поведения вызывается в ИИ.


Selection Variables ассоциированные с ИИ модифицируются несколькими путями.

  • ИИ система создает новые сигналы, которые передаются в систему поведения (например, система The Perception (система перцепции) определяет, что ИИ теперь может видеть игрока).
  • ...Сигналы получаются BHS принадлежащем ИИ и обрабатываются как определено в секции Signal Variable.
  • Текущее поведение ИИ получает сигнал и непосредственно изменяет Selection Variable.
  • ИИ система сама непосредственно изменяет Selection Variable, принадлежащую ИИ (это обычно не требуется/в этом нет необходимости).

Как пример, поведение может содержать логику условий смены поведений исходя из текущего окружения. Скажем, например, что наше поведение под названием «Investigate» имело сигнальный метод «OnSoundHeard», который получен от ИИ-системы, когда новый звук был зарегестрирован ИИ-перцепцией.


OnSoundHeard = function( self, entity, fDistance )
  if (fDistance < 5) then
     AI.SetBehaviorVariable(entity.id, "AwareOfEnemy", true);
  end
end,

Так, если новый звук сгенерировался где-то совсем рядом с ИИ, произойдет обновление статуса поведения до состояния «Attack», хотя визуально цель еще не определена.

Следует отметить, что смена поведения не так уж тяжела для движка, но если ИИ постоянно меняет поведения, то это может стать сложно для дебага и следования за ним. При разработке соответствующего поведения, старайтесь не думать, что поведения являются индивидуальными действиями. Думайте о них больше, как об обеспечивающих относящихся к событию по логике действиях. Например, «FireFromCover» поведение может содержать действия сидения внутри укрытия некоторое время, выглядывания из-за укрытия в поисках цели, ведение слепого огня и покидание укрытия и стрельбу конкретно по цели.


Заимствование блоков поведения между разными BHS

Нет ОБЯЗАТЕЛЬНОЙ связи между BHS и поведениями, которое оно использует. Поведения могут свободно взаимно использоваться разними BHS пока поведение работает с конкретным ИИ-типом. Смотрите документацию по Поведениям и Голпайпам подробнее по поводу правильной настройки поведения.

В помощь взаимному использованию базовых поведений, есть возможность обявить блоки поведения «Blocks». Они находятся в своих собственных XML-файлах в той же директории (или поддиректориях), где и BHS-файлы.

Чтобы продемонстрировать это на том же примере, должен быть файл под названием «Common.xml», сидящий в базовой «Selection Tree» папке.

Это может выглядеть следующим образом:

<Blocks>
  <Block name="CommonVars">
    <Variable name="AwareOfSound"/>
    <Variable name="AwareOfEnemy"/>
  </Block>
  <Block name="CommonSignalVars">
    <Signal name="OnHearSound" variable="AwareOfSound" value="true"/>
    <Signal name="OnEnemySeen" variable="AwareOfEnemy" value="true"/>
    <Signal name="OnNoTarget" variable="AwareOfSound" value="false"/>
    <Signal name="OnNoTarget" variable="AwareOfEnemy" value="false"/>
  </Block>
</Blocks>

Файл может содержать любое число «Blocks», и каждый блок абсолютно отдельный относительно всех других «Blocks». Подразумевается, что они модульные и подгружаются в BHS-файлы, когда это необходимо. Чтобы включить Block в BHS, вы добавляете ссылку в соответствующую секцию.


В качестве примера, наша selection variable секция может быть заменена на гораздо более короткую:

<Variables>
  <ref name="CommonVars"/>
</Variables>

а signal variable секция - на:

<SignalVariables>
  <ref name="CommonSignalVars"/>
</SignalVariables>

Таким образом, вы можете передать конкретный набор Selection Variables и Signal Variables всем вашим ИИ-типам. Использование такого формализма призвано сделать ваши файлы поведения более чистыми и управляемыми.

Давайте повторно вернёмся в Leaf Translations концепт из выше приведенного в статье материала. Скажем, мы определили другой логический блок таким образом:

<Block name="CommonBehaviorTree">
  <Priority name="CommonRoot">
    <Priority name="Combat" condition="AwareOfEnemy">
      <Leaf name="Attack"/>
    </Priority>
    <Leaf name="Investigate" condition="AwareOfSound"/>
    <Leaf name="Idle"/>
  </Priority>
</Block>

Вы можете далее заменить порцию Дерева выбора BHS нашего гранта следующим:

 
<Priority name="Root">
  <Ref name="CommonBehaviorTree"/>
</Priority>

Теперь из-за того, что у нас есть leaf translations секция, которая подменяет стандартные имена на ИИ-архетип специфичные имена поведения, всё будет работать. Таким образом вы можете разделять дерево поведений между множеством разнообразных ИИ-типов, но тем не менее иметь уникальные поведения, заданные для каждого листа дерева. Чтобы продемонстрировать это, нам понадобится другой ИИ-тип, называемый «Alien». Скажем, что мы ожидаем, чтобы «Alien» разделял те же самые базовые типы поведения. Мы можем дублировать BHS от «Grunt» и заменить «Leaf Translation» секцию на:

<LeafTranslations>
  <Map node="Idle" target="AlienIdle"/>
  <Map node="Investigate" target="AlienInvestigate"/>
  <Map node="Attack" target="AlienAttack"/>
</LeafTranslations>

Предполагая, что те поведения существуют, «Alien» ИИ-тип будет готов, и всё ещё иметь уникальное ИИ поведение.