WarCraft 3: Как проиграть анимации типа Stand 2, Spell-4

» Раздел: Триггеры и объекты

В кинематиках для придания большей реалистичности действию часто используется триггерная команда
Анимация - Play unit animation.
Например, если какой-то герой по сюжету должен прыгать от радости, а он вместо этого стоит неподвижно, получится как-то неестественно. Самый лучший выход в этом случае - проиграть анимацию прыжка. Например, у Лорда Ужаса (Дридлорда) прыжок - это анимация Stand-3. И вот тут-то как раз и возникает проблема. Оказывается, что команда проигрывания анимации работает сразу с группой анимаций. Т.е. при попытке проиграть не Stand, а Stand 2, Stand 3 или Stand 4 результат будет непредсказуемый. Скорее всего, проиграется обычная анимация Stand (она же - Stand 1) или же вообще ничего не проиграется.
В случае с лордом ужаса проблема вполне разрешима - достаточно использовать для кинематики Вариматаса - у него есть анимация прыжка Spell Third, которая проигрывается без проблем.
Но в любом случае, очень обидно, что большинство анимаций юнитов оказываются триггерно недоступными. Особенно обидно бывает, когда импортируешь в карту модель WoW 10Мб весом, а потом оказывается, что из всех тамошних анимаций можно использовать лишь 3-4 штуки. Остальное же - просто мёртвый груз, ибо War вообще не понимает анимации с нестандартными именами (навроде Attack Very-Very Hard).
Триггерно решить эту проблему невозможно. А вот у JASS'еров есть шансы. Думаю, многие любители JASS во время просмотра common.j обращали своё внимание на функцию
native SetUnitAnimationByIndex takes unit whichUnit, integer whichAnimation returns nothing
Судя по её названию, она должна проигрывать анимацию не по имени, а по номеру. Т.е. всё, что надо сделать, это подставить туда номер анимации - и готово, имя не имеет значения!
Эх, если бы всё и впрямь было так просто :(. Blizzard'ы не были бы Blizzard'ами, если бы не придумали очередной способ сверления зубов дракона через задний проход. Т.е. данная функция попросту не работает! Причём абсолютно, все её вызовы просто игнорируются и на анимацию никак не влияют.
Так как же всё-таки проиграть нужную анимацию юнита?
Первое, что для этого нужно сделать - создать анимационный тег. Это особый объект, представляющий собой всего лишь список всех анимаций юнита. Создаётся он при помощи ещё одной "загадочной" JASS-функции:
native AddUnitAnimationProperties  takes unit whichUnit, string animProperties, 
                                                                                                      boolean add returns nothing
Что только о ней не пишут во всяких мануалах! По одной версии, она добавляет новые имена анимаций; по другой - новые анимационные свойства (что бы это значило). В JASSWiki данная функция "поясняется" так: "Добавляет/удаляет анимационные свойства юнита".
На самом же деле она всего лишь создаёт анимационный тег (список анимаций юнита) и "цепляет" его на указанный юнит. Рассмотрим параметры этой функции:
  • whichUnit - всего-навсего тот юнит, анимационный тег которого мы хотим создать (или удалить, т.к. эта же функция способна и удалять анимационные теги).
  • animProperties - имя анимационного тега. Может быть любым. Используется для дальнейших ссылок на анимационный тег. Если ссылки на тег в дальнейшем не понадобятся, то в этом параметре можно передать null. Тогда ссылка на тег теряется и происходит утечка памяти (всем участникам команды DotaTeam рекомендуется всегда передавать сюда null).
  • add - если сюда передать true, то тег создаётся; если false - удаляется (при условии, конечно, что на юните есть тег с указанным именем). Все, кто озабочен утечками, должны непременно удалять теги, когда они становятся ненужными. Все остальные могут упростить себе жизнь и оставить теги неудалёнными (благо в любой кинематике и без того утечек масса).
Кстати, триггерщики для создания тега могут воспользоваться командой
Анимация - Add/Remove unit animation tag. Вообще говоря, это очень странно: создать тег триггеры позволяют, а работать с ним - нет :).
Итак, тег создан (для тех, кто забыл - напоминаю: тег есть список всех анимаций юнита). А вот теперь смело вызываем SetUnitAnimationByIndex. Триггерщики могут воспользоваться для этого Custom script:
call SetUnitAnimationByIndex(gg_unit_hfoo_0002,3)
Первый параметр этой функции - юнит, анимацию которого нужно проиграть. Второй - номер анимации (нумерация идёт с нуля, 0 - это, как правило, Stand 1).
Триггерщикам будет несколько сложновато определять, что нужно написать в качестве юнита :), выглядит это действительно страшновато. Ну что ж, могу посоветовать создать какой-нибудь триггер для тестирования, содержащий всего 1 команду, использующую данный юнит. Затем конвертировать триггер в текст и глянуть имя глобалки юнита. (Надеюсь, я вас ещё не загрузил?)
Вторая проблема - определить номер нужной анимации. WE тут ничем не поможет, т.к. его окошко анимаций сортирует их по алфавиту, а не по номеру. Номер можно определить, открыв файл модели юнита в блокноте (лучше - в виде MDL), War3Viewer, MdlVis, W3ME или подобной программе. После чего просто подсчитать анимации (от нуля), пока не дойдёте до нужной.
Итак, ещё раз (кратко, для триггерщиков):
  1. Анимация - Add/Remove unit animation tag. Создаётся список анимаций на юните. Достаточно создать тег один раз, и можно проигрывать сколько угодно анимаций для этого юнита.
  2. Custom script: call SetUnitAnimationByIndex(gg_unit_XXXX_YYYY,N) предварительно определив имя глобалки, содержащей юнит и номер желаемой анимации.
Ну, вроде и всё. Если что-то будет непонятно - пишите. До скорых встреч :end:

Дополнение - загрузка игры

Здравствуйте, с вами ScorpioT1000 :)
Появилась новая проблема - сбивание анимации, применённой с помощью "SetUnitAnimationByIndex" функцией "SetUnitPosition".
Возникает она после того, как игрок загрузит сохранённую ранее игру на вашей карте.
Решение "простое" - пересоздаём этого юнита.
Подробнее:
  1. Отключаем все наши системы, "затрагивающие" нашего юнита.
  2. Отключаем все триггеры, реагирующие на событие смерти нашего юнита (для этого просто надо иметь переменную типа bool в условиях и применять её где надо).
  3. заменяем нашего юнита на того-же, например:

my_unit_var = ReplaceUnitBJ(my_unit_var, MY_UNIT_ID, bj_UNIT_STATE_METHOD_ABSOLUTE)
  1. Включаем все триггеры, реагирующие на событие смерти.
  2. Включаем всё остальное.

Просмотров: 18 144

TiM #1 - 11 лет назад -9
напишите лучше как взрывать юнита,когда на него напали.
или как сделать так, чтобы двери открывались,когда юнит умирал
Markiz #2 - 11 лет назад 1
Алексей, Add Animation Tag - добавляет "суффикс" к анимации юнита (пример суффикса "Alternate", "Upgrade"), вот почему дота тим делает именно пустой анимационный таг.
ADOLF #3 - 10 лет назад 0
хз, у меня анимация проигрывалась по индексу БЕЗ предварительного создания тега. Советую проверить.
Alibek #4 - 10 лет назад 1
еще один плюс здесь есть
она воспроизводится прямо в игре без синематик мод))
крутая статья
Kreker #5 - 10 лет назад 1
А можно переменным это действие задавать? Вот так например:
call SetUnitAnimationByIndex(gg_unit_udg_<имя переменной>,N)
Вот у меня, например, так не работает(
Ferrum #6 - 9 лет назад 0
Статья может помочь начинающим.
Death of God #7 - 9 лет назад 1
Отличная статься! Соглашусь с ADOLF, у меня анимация также проигралась без создания тега.
GodMax #8 - 8 лет назад 1
я написал вот так:
call SetUnitAnimationByIndex(<имя переменной>,N).
и вы не поверите, но всё подействовало. ))Так что не надо говорить что Близард всё через задницу делает.
BioAleks #9 - 8 лет назад -3
Это для нубоф статья
Bonezzz #10 - 8 лет назад 2
Никак не могу найти (Мне казалось, в чьей-то статье видел), как сделать анимацию, к примеру, набегу. То есть, например, Джагернаут бежит и проигрывает анимацию удара с прыжком.. Если кто знает что-нибудь об этом или знает ссылку на статью, просьба - написать в личку, заранее спасибо.
ScorpioT1000 #11 - 7 лет назад 1
!!!
добавил некоторую полезную инфу внизу
SLI #12 - 6 лет назад 0
супер, респект Алексею!
rPeg_ #13 - 5 лет назад 0
полезно
Olifem #14 - 5 лет назад 2
А может ли кто нибудь сделать карту-пример?
Sovereing2027 #15 - 4 года назад 0
Анимация - Add/Remove unit animation tag
Автор эту функцию не так понял видимо
ScorpioT1000 #16 - 4 года назад 2
Sovereing2027:
Анимация - Add/Remove unit animation tag
Автор эту функцию не так понял видимо
Это ты путаешь функции.
Doflamingo #17 - 4 года назад -4
Полезная инфа, большое спасибо. Хотя анимки у меня итак итак проигрывались через триггеры, но бывало это не всегда. Может это поможет.
icefrost #18 - 4 года назад 0
ScorpioT1000, функция Add/Remove unit animation tag добавляет ко всем приказам(неважно отдан приказ триггерно или во время игры, кликнув мышью) дополнение к названию анимации равное названию тэга. Вот пример:
Если какой-то юнит имеет анимации: stand, stand alt, attack, attack alt, spell, spell alt итд... тогда если дать ему триггерно тэг с названием "alt" то любое действие которое должно вызвать проигрывание анимации у юнита, автоматически проигрывает не то что обычно, а (то, что обычно + название прикрепленного тэга), в случае с юнитом-примером при ссылке на анимацию stand будет проигрываться анимация stand alt, при ссылке на анимацию attack будет проигрываться attack alt итд итп... я сам эту функцию использую больше 2 лет, и всё всегда работает именно так как я описал.