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

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

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


Содержание

Скрипты поведения

Краткий обзор

Для того, чтобы ИИ реагировали на игрока и окружающую среду, они должны иметь назначенные поведения (behavior). Как эти поведения расположены и выбираются, рассматривается в руководстве «Дерево выбора поведения»; данное руководство будет рассматривать, как определить индивидуальное поведение, и как они интегрируются с ИИ системой. Скрипт Behavior содержит логику о том, как конкретный ИИ должен реагировать на стимулы в текущих событиях, такие стимулы, как обнаружение игрока, слышание звука, получение сигнала от члена группы, приземление гранаты к ногам. Все эти изменения окружающей среды переводятся в сигналы, обрабатываемые как методы таблицы поведений (behavior table). Таким образом, текущее поведение ИИ имеет полную власть над его ответами. Помимо просто реагирования на стимулы, поведение поддерживает состояние ответа на них ИИ. Поэтому, как только ИИ начинает однажды какое-то поведение (behavior), оно будет продолжать диктовать все ИИ действия до того момента, пока другое поведение behavior не будет выбрано.


Поведения определяются по таблицам LUA скриптов и могут наследовать функциональность родительских базовых поведений. Это наследование обеспечивает значительную гибкость для создания множества уникальных ИИ типов, сохраняя при этом много общего поведения.


Если ИИ не назначено действующее Дерево Выбора Поведения (Behavior Selection Tree или сокращенно BHS) по крайней мере с одним действующим поведением по умолчанию, то ИИ НЕ БУДЕТ иметь поведения вообще. Перцепция ИИ поступающих сигналов (т.е. обработка воспринимаемых самим ИИ сигналов) функционирует независимо и будет по прежнему посылать сигналы, но ЕДИНСТВЕННОЕ, что ИИ будет в состоянии сделать - это повернуться по направлению к текущей «Цели Внимания» («Attention Target»).


Создание поведения

ИИ являются назначенными поведениями через BHS. Дерево добавляется посредством Behavior Selection Tree свойства под полем ClassProperties ИИ архетипа в CryENGINE Sandbox. Хотя дерево ассоциирует поведения с ИИ, поведения должны определяться индивидуально.

Поведение определяется в таблице LUA в базовой директории игры под «Scripts/AI/Behaviors». При добавлении поведения или внесении изменений в существующее, перезагрузка скрипта в Sandbox перезагрузит его без необходимости повторного запуска редактора.

Как пример давайте создадим новое поведение называемое «Idle», которое наследует от другого поведения таблицы, называемого «AIBaseBehavior».

Таблица поведения начинается со следующего объявления:

local Behavior = CreateAIBehavior("Idle", "AIBaseBehavior",  
{  
  TABLE METHODS...  
}

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

Конструкторы

Все поведения ДОЛЖНЫ иметь Constructor метод и по желаю иметь Destructor метод. Constructor метод является критическим, т.к. он вызывается ВСЕМИ и ВСЕГДА, когда ИИ переключается на поведение. Он должен заботиться об инициализации любого статуса сущности и начинать ИИ действия, которые будут представляться во время работы поведения.

Например, наш idle конструктор поведения может выглядеть так:

Constructor = function (behavior, entity)  
  if ( entity:IsActive() ) then  
    entity:SelectPrimaryWeapon()  
  end  
end,

Деструкторы

Destructor с другой стороны вызывается при выходе из поведения и при переходе на новое. Он может очистить статус сущности или сохранить некоторый новый статус для будущего вызова обратно в это поведение. Скажем, например, мы хотим отследить последнюю позицию, когда ИИ был idle:

Destructor = function(behavior, entity)  
  entity.lastIdlePosition = entity:GetPos()  
end,

Сигнал поддержки

Помимо этого, также возможно интегрировать поведение с сигналами ИИ системы. (иначе известными как события events). Примерами могут быть:

OnNoTarget = function( self, entity )  
  -- вызывается когда ИИ перестает видеть привлекающую внимание цель  
end,  
 
 
OnEnemySeen = function( self, entity, fDistance )  
  -- вызывается когда ИИ видит живого врага  
end,  
 
OnGrenadeSeen = function( self, entity, fDistance )  
  -- вызывается когда ИИ видит гранату  
end,

События/сигналы ИИ системы функционируют с аргументами. Имя функции, это имя события и список аргументов выглядит следующим образом:

1. self (сам) - Этот аргумент является ссылкой к самой таблице поведения. Это позволяет методу таблицы поведения вызывать другой метод поведения, т.к. он постоянно держит ссылку на себя.

Например:

ProcessVisual = function( self, entity, fDistance )  
end,  
 
OnEnemySeen = function( self, entity, fDistance )  
  -- вызывается когда ИИ видит живого врага  
  self:ProcessVisual(entity, fDistance)  
end,

«OnEnemySeen» функция вызывает «ProcessVisual» метод того же поведения. Обратите внимание, что при использовании двоеточия (:) в форме вызова метода, первый аргумент self неявно передается - как неявный аргумент в С++ классах. Если метод (.) используется для вызова метода, тогда self аргумент должен быть явно передан, как:

self.OnEnemySeen(self, entity, fDistance)

Это строго CryEngine поведение Lua, и упоминается здесь только для ясности.

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

Например:

ProcessVisual = function( self, entity, fDistance )  
 entity.AI.lastVisualDistance = fDistance  
end,

3.Добавочные (Additional) аргументы передаются в качестве значений данных, необходимых для обработки передающегося сигнала. Как представлено, «OnEnemySeen» функция имеет третий аргумент - расстояние до игрока-цели. Приложения содержат полный список всех системных определенных событий и всех аргументов, которые им передаются.


Дополнительные методы

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


Пример обработки сигнала

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

«Idle» поведение может быть весьма простым для целей демонстрации:

local Behavior = CreateAIBehavior("Idle",  
{  
  Constructor = function (behavior, entity)  
    if ( entity:IsActive() ) then  
      entity:SelectPrimaryWeapon()  
    end  
  end,  
}

Такое поведение не делает ничего кроме выбора оружия и стояния на месте, но оно позволяет нам экспериментировать с ответами на некоторые сигналы ИИ системы. Для того, чтобы отреагировать на некоторое конкретное событие, всё что нам нужно сделать, это создать логику для обработки события внутри поведения как описано ранее в руководстве - например, если мы хотим сделать что-нибудь, когда враг видит игрока, мы напишем что-нибудь в функции «OnEnemySeen» поведения.

В качестве упражнения мы будем выводить некоторый текст, когда враг видит игрока. Этот текст выбет выводиться в HUD, так что мы должны сделать HUD видимым в режиме игры редактора, набрав «cl_display_hud 1» в консоли.

Далее давайте добавим «OnEnemySeen» функцию:

OnEnemySeen = function( self, entity, fDistance )
  -- вызывается когда враг видит живого игрока
  Hud:AddMessage("I SEE YOU");
end,

Теперь каждый раз, когда враг видит вас, это будет отображаться таким текстом в консоли. Чтобы проверить это, перезагрузите скрипты и перейдите в режим игры. Приближайтесь к врагу до тех пор, пока вы не увидите текст, отображенный в вашем HUD.


Обратите внимание, что функция события вызывается ОДИН раз, когда враг впервые видит игрока, а НЕ каждый фрэйм после этого события. Это сделано для того, чтобы минимизировать ненужные вызовы скрипта (которые могут быть значительными по объему), предполагая, что только изменеия статуса должны быть зарегистрированы в поведениях. Когда однажды ИИ начинает видеть игрока, предполагается, что он будет продолжать его видет, пока не указано иное. Другая вещь, на которую следует обратить внимание, это то, что враг НЕ начинает видеть вас немедленно, но только после того, как стелс-о-метр возрастает до максимального значения. Это нормальная операция и может быть отредактирована в С++ в dll игры.

События вызываются, не имея знания о статусе в поведении. Чтобы проиллюстрировать это, давайте обработаем другое системное событие, которое случается во время игры - «OnThreateningSoundHeard» событие:

OnThreateningSoundHeard = function( self, entity )  
  -- вызывается, когда враг слышит устрашающий звук
  Hud:AddMessage("I HEAR SOMETHING!!");  
end,

Чтобы протестировать это, зайдите в режим игры в позицию напротив ИИ, который имеет состояние «idle», и затем выстрелите в воздух. ИИ услышыит звук выстрела, и прореагирует используя функциональность в «OnThreateningSoundHeard». После услышания звука, ИИ повернёт лицо по направлению выстрела и следовательно увидит игрока. Это вызовет «OnEnemySeen» событие. Почти любая логика пожет быть выполнена через скрипты LUA поведения. Имея доступ ко всем глобальным объектам в LUA статусе, Вы можете повлиять на рендеринг, физическое состояние мира, проигрывание звуков или музыки, или конкретных анимаций. Это делает сценарии ИИ скриптинга простыми и в то же время довольно мощными.

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