Alex3D 28 июн 2013, 00:37
Всем доброго времени суток!
Вот решил перевести и прокомментировать элементы Behavior Tree из Rain{Indie}. Замечания и исправления приветствуются.
КОНТЕЙНЕРЫ (Containers)
Behavior Tree Root
(Корень дерева поведений)
Его имя - это и имя всего дерева поведений, и файла этого дерева. Указывается при создании, потом изменить это имя нельзя.
Предназначен для инициализации переменных. Занести значения в виде строк true или false не удалось, надо заносить их в виде целочисленных аналогов - 1 и 0.
Если в Mind.RootName объекта ИИ ничего не указано, то автоматически выполняется первый вложенный в корень узел. Редактор позволяет заносить для Корня несколько child'ов, и выполнение можно начать с любого из них, указав нужное имя в Mind.RootName.
Важно! - выполнение можно начать только с child'а ПЕРВОГО уровня вложенности - если указать что-то другое (или вообще ошибочное имя), то никакой ошибки в среде не индицируется, однако ничего и не выполняется.
Sequencer
(Пошаговый)
Выполняет все вложенные узлы по порядку, пока какой-либо из них не завершится Failure (тогда возвращает Failure), либо пока все они успешно не завершатся (тогда возвращает Success).
Selector
Переключатель
Все узлы выполняются по порядку, если какой-то из них завершится Success, то выполнение этого контейнера прекращается с результатом Success. Если никакой из них не завершится Success, то контейнер возвращает Failure.
Parallel
(Параллельный)
Выполняет всех своих child'ов "одновременно", в произвольном порядке (in no particular order) (!).
Параметры
Fail - определяет, вернёт ли контейнер Failure, если некоторые или все его child'ы вернут Failure:
- Any - если хотя бы один из них окончится неудачно
- All - если все они окончатся неудачей
Succeed - определяет, вернёт ли контейнер Success, если некоторые или все его child'ы вернут Success:
- Any - если хотя бы один из них окончится удачно
- All - если все они окончатся удачей
Tie Breaker - если оба атрибута Fail и Succeed установлены в Any, определяет, что вернуть контейнеру, если некоторые его child'ы вернули Succeess, а некоторые Failure.
Замечание от авторов.
На каждом такте, пока контейнер не завершил работу, он исполняет ВСЕ свои child'ы (в непредсказуемом для нас порядке, как было сказано выше), даже если окончательный результат работы контейнера на этот момент уже ясен.
Замечание от меня.
"Произвольный порядок" выполнения вложенных узлов видимо подразумевает, что внутри одного параллельного контейнера его child'ы не должны пользоваться никакими данными, которые меняют или предоставляют другие child'ы. Мне как программисту это легче всего представить как работу в разных потоках без какой-либо синхронизации по данным. Это, конечно, серьёзное ограничение, ну что ж...
Iterator
(Итератор)
То же самое, как Sequencer, за исключением того, что повторяется указанное в параметре Count число раз.
Возвращает Success, если на всех итерациях все его child'ы вернули Success.
В ином случае - Failure.
Замечание.
На сайте поддержки заявлено, что Count можно указывать в виде выражения, и, как в приличных циклах типа for, его значение вычисляется ПЕРЕД первой итерацией и возможные его изменения в процессе итераций влияния на число итераций не имеют. А когда же новое значение будет использоваться?
"...new value won't be used until the behavior tree finishes and begins executing again."
Не очень ясно, достаточно ли нового выполнения ветки, в которой находится этот итератор, или всё дерево должно пойти выполняться заново. Впрочем, вопрос теоретический, т.к. никакого "выражения", кроме просто числа, занести в поле Count не удалось.
Random
(Случайный выбор)
Из всех своих child'ов выбирает одного случайным образом и его выполняет. Возвращаемый результат контейнера равен результату выполнения этого child'а.
ДЕЙСТВИЯ (Actions)
Animate
(Анимировать)
Проигрывает на объекте ИИ указанную в параметре Animation анимацию, макс. длительность этого указывается в Wait For Second, как она окончится и будет ли повторяться - а параметре Animation Wrap.
Плавность перехода к-из этой анимации в начале и конце определяется параметрами Fade In Time и Fade Out Time.
Failure возвращается только в случае, если произошла какая-то ошибка.
Некоторые ссылки на сайте разработчика ведут в никуда, вероятно, вопрос с некоторыми параметрами ещё решается так или иначе.
Assign
(Присвоить)
Присвоение переменной значения, определяемого выражением. Также можно (или нужно) указать мин. и макс. допустимые значения. Т.е. фактически присвоится clamp(значение выражения, min, max).
Что знаменательно - ВСЕГДА возвращает Success.
Audio
(Аудио (и зачем я это перевожу?))
Параметры
Audio Source - имя GameObject'а, имеющего компонент AudioSource, причём обязательно находящегося в иерархии нашего объекта ИИ.
Delay - задержка перед проигрыванием
Wait Until Done - ждать ли, чтобы проигралось до конца.
Самоочевидно, что AudioSource уже должен иметь указанный медиа-файл для проигрывания, т.к. его имени в параметрах нет.
Если произошла ошибка, возвращает Failure.
Замечание от меня
Не ясно, вернёт или Running в процессе проигрыша, если не стоит чек Wait Until Done:
"Running - if Wait Until Done is enabled the AudioSource is currently playing."
Condition
(Условие)
Возвращает булевский результат вычисления указанного в Expression выражения.
Success: true, !=0 (особо замечу - не "больше нуля", а "не равно нулю", т.е. и отрицательные тоже)
Failure: false, ==0
Custom Action
(Пользовательское действие)
Выполняет пользовательский скрипт, являющийся наследником специального класса Action.
Шаблон можно создать из формы редактирования дерева. В шаблоне надо заполнить четыре функции.
1. Конструктор Как минимум надо задать имя класса.
2. Start Для инициализации. Вызывается один раз до последовательности вызовов Execute
3. Execute Потихоньку делает всю нужную работу. Вызывается множество раз в каждом такте.
4. Stop Вызывается после всей работы, независимо от того, успешный или нет результат. Возможно, также вызывается для принудительного прерывания работы скрипта из вызвавшего его Дерева Поведений.
Возвращаемый результат имеет смысл только для Execute (пока он не закончил, надо возвращать Running, потом - Success или Failure).
Указанный во всех членах параметр Agent - это ссылка на ИИ. Именно он может интересоваться, ощущать, двигаться, смотреть и т.п. Имеет такие члены, как Agent.Avatar, Agent.Kinematic, Agent.MoveTo...
Вообще надо смотреть примеры и документацию, так не расскажешь на одной странице.
В параметре Class указывается имя класса нужного скрипта (того самого наследника от Action).
Debug
(Отладка)
Позволяет записать в лог указанную в Message фразу (не ясно, можно ли в ней использовать выражения, или это должен быть строковый литерал).
Возвращает то, что указано в поле Returns.
Detect
(Обнаружить)
Параметры
Sensor - имя объекта GameObject, имеющего компонент-сенсор, и являющегося child'ом к объекту ИИ (не ясно, может ли это быть сам объект ИИ)
Aspect - имя признака (Decoration), который мы пытаемся обнаружить. Не ясно, можно ли указываеть несколько признаков (например, через запятую)
Variable - если обнаружится GameObject с нужным признаком (Decoration), то ссылка на него будет помещена в переменную с указанным в этом поле именем.
Возвращает Success, если был обнаружен подходящий объект с нужным признаком и ссылка на него была помещена в Variable.
Failure в ином случае.
Mecanim IK
(Управление инверсной кинематикой в стиле Mecanim)
Используется для того, чтобы посмотреть на что-то, указать рукой или поставить туда ногу. Набор параметров зависит от того, какое действие выбрано. Это действие требует параметра Repeat Forever, либо же должно быть помещено в зацикленный контейнер (чтобы, как я понимаю, было время отыграть это движение).
Про возвращаемое значение написано как-то несмело, возможно, неуспех наступит при невозможности отыскать Mecanim Animator у Аватара.
Mecanim Move
(Передвижение в стиле Mecanim)
Довольно хорошо описана в туториалах и демках.
Параметры
Move Target - координата или переменная, полученная перед этим, например, действием Detect, куда надо идти
Look Target - аналогично на что при этом надо смотреть
Move Speed - вроде как скорость, но не всегда этот параметр оказывает действие
Damp Speed - степень "сглаживания" анимаций. Сдаётся мне, что Rain + IKController напрямую двигают объект ИИ, и те анимации, которые перемещают root, этому передвижению только мешают. Собственно для сглаживания этого противоборства параметр и нужен.
В следующие параметры заносятся имена переменных машины состояний Mecanim-анимаций.
В зависимости от того, какие параметры используются машиной состояний анимаций, те имена и заносить. Всё зависит от этой машины. Для машины состояний из примера в примере всё рассказано.
Возвращает Failure, если невозможно проложить путь к цели, или если цель исчезла (переменная приобрела значение null)
Вроде как прокладывает путь динамически, т.е. движущаяся цель тоже в конце концов будет настигнута.
Mecanim Parameter
(Параметр Mecanim-машины состояний)
Собственно, можно напрямую послать нужный параметр в машину состояний анимаций Mecanim.
Параметры
Parameter - имя параметра машины состояний
Parameter Type - тип этого параметра (Boolean, Integer, Float, Vector, Quaternion)
Value - значение параметра (можно и в виде выражения, по словам авторов)
Damp Time - задержка, после которой параметр будет применён (не очень ясно зачем она нужна, вероятно опять же для сглаживания переходов анимаций)
Возвращает Failure, если параметр не мог быть применён (скорее всего Mecanim не найден)
Move
(Движение)То же, что и Mecanim Move, но без Mecanim. Анимация задаётся напрямую.
Timer
Задержка на указанное число секунд
Yeld
Пауза Дерева Поведений на один такт. Для лучшей производительности.
Что-то типа Application.ProcessMessages для оживления экрана? Не ясно. Или чтобы анимации поглаже состыковать...
Всегда возвращает Success.