От Line Trace до Full Body IK: Как заставить персонажа ходить по любой поверхности
На днях разбирался как работает ik система подстройки ног на примере unreal манекена , надеюсь будет полезно ( это скорее заметки , нежели чем полноценный урок)
Разберем Как работает риг От эпиков
Идем в функцию FootTrace
Вот тут мы рассчитываем точки для трассировки (Sphere Trace) для каждой ноги.
1. Определяем горизонтальную проекцию стопы (X,Y)
Сначала мы смотрим, где нога находится в анимации, чтобы луч всегда был строго под ней.
- Берём позицию кости стопы c помощью ноды get transform - bone . (например, ik_foot_l - на скриншоте их нет - их эпики указывают чуть позже ) по осям X и Y.
- К оси Y можно добавить небольшое смещение (например, +5), чтобы сдвинуть "сенсор" луча из-под щиколотки под подушечку стопы. Это делает постановку ноги более естественной.
- Присоединяем это к ноде ADD и Substract по осям X ,Y
2. Рассчитываем высоту (Z)
Чтобы луч гарантированно находил землю на любом рельефе, мы задаем ему начальную и конечную точки, привязанные к высоте (Root).
- Начальная точка (Start):
- Берем данные с рутовой кости с помощью ноды get transform - bone
- Присоединяем это к ноде ADD и Substact по осям Z
- в ноде Add во вкладке B ставим 30 для оси Z
- и в ноде Substract для оси Z , во вкладке B ставим 50 )
- Зачем добавляем 30 ?: В анимации нога может "войти" в склон или ступеньку. Если начать луч изнутри объекта, он сработает неправильно.Решение: Высота (Root.Z) + 30 юнитов. Мы принудительно поднимаем начальную точку высоко над землёй, гарантируя, что луч всегда стартует из пустого пространства.
- Зачем мы ставим 50 в Substract ?
- Проблема: Если персонаж спускается со склона, земля может оказаться ниже, чем обычно. Короткий луч может "не дотянуться" до неё.Решение: Высота (Root.Z) - 50 юнитов. Мы делаем луч заведомо длиннее, чем нужно, чтобы он, как длинный "щуп", гарантированно пересёк любую поверхность под ногами.
3. Собираем все вместе
- Собираем Start: (Стопа.X, Стопа.Y + 5, Таз.Z + 30)
- Их собираем через ноду Add
- Собираем End: (Стопа.X, Стопа.Y + 5, Таз.Z - 50)
- Их собираем через ноду Substract
- Запускаем Sphere Trace By Channel из Start в End с небольшим радиусом (например, 3.0) для более надёжного контакта.
4. Возвращаем результат
Если луч нашёл поверхность, мы берём результат столкновения (Hit Location ) и передаем его дальше (в Return Node)
Идем в сам риг
Логика включения и выключения IK
проверяем для начала должны ли мы включать ik или нет ( это делается через ноду Branch ) у эпиков если персонаж в воздухе то логика ik не работает ( значение для булевной переменной мы указываем в анимационном блюпринте персонажа и оставим это за рамками этих заметок)
- Если нет :Set ZOffset_L_Target: В переменную для левой ноги принудительно записывается 0.0.
- Set ZOffset_R_Target: В переменную для правой ноги также записывается 0.0.
Итог ветки: IK-смещения обнуляются, и ноги персонажа просто следуют за основной анимацией, свободно болтаясь в воздухе. это мы используем когда персонаж в воздухе ( в прыжке)
Если же наш персонаж не падает то
Путь True (Персонаж на земле)
- Что происходит: Если Should Do IKTrace истинно, выполняется верхняя ветка.
- FootTrace (для левой ноги): Запускается ваша локальная функция трассировки для левой ноги (ik_foot_l).( обратите здесь во вкладке Name мы указываем название кости для которой делается line trace
- Set ZOffset_L_Target: Результат трассировки (Offset.Z — вертикальное смещение) сохраняется в переменную для левой ноги.
- FootTrace (для правой ноги): То же самое происходит для правой ноги.
- Set ZOffset_R_Target: Результат сохраняется в переменную для правой ноги.
Важно все расчет мы делаем для специальных костей с приставкой ik ( эти кости стандартно идут в unreal манекене)
Alpha Interpolate (Сглаживание-)
- Что делает: Этот узел работает как "доводчик". Он не позволяет значению мгновенно измениться. Вместо этого он плавно "ведёт" текущее значение к целевому с заданной скоростью.
- Value: Сюда подаётся целевое смещение (например, -10 см), рассчитанное на предыдущем шаге с помощью Line Trace.
- Interp Speed Increasing/Decreasing: Это скорость сглаживания. Вы можете задать разную скорость для движения вниз и вверх, чтобы, например, нога "вдавливалась" в землю медленнее, чем отрывалась от неё.
Как работает вся цепочка
Логика одинакова для левой (_L) и правой (_R) ноги:
- Получаем цель: Код берёт переменную Get ZOffset_L_Target, в которой хранится "сырое" смещение для левой ноги.
- Сглаживаем значение: Узел Alpha Interpolate вычисляет новое, сглаженное значение, плавно двигаясь к цели.
- Сохраняем результат: Это сглаженное значение сохраняется в финальную переменную Set ZOffset_L.
Итог и назначение
Этот код — "амортизатор" для системы IK.
- Без этого сглаживания, при ходьбе по неровностям, ноги персонажа мгновенно "прыгали" бы на новую высоту каждого камня. Это выглядело бы очень резко, неестественно и "дёргано".
Коррекция положения таза
- Get ZOffset_L и Get ZOffset_R — получаем значения смещения по оси Z (высоты) для левой и правой ноги.
- Less (A < B) — проверяет, меньше ли смещение левой ноги, чем правой.→ True: левая нога ниже → использовать ZOffset_L → False: правая нога ниже или на том же уровне → использовать ZOffset_R
- If (Select node) — выбирает одно из двух значений в зависимости от результата Less: True: передаёт ZOffset_L False: передаёт ZOffset_R
- Set ZOffset_Pelvis — устанавливает смещение таза на наименьшее значение из двух стоп.
Что это значит на практике?
Допустим:
- Левая стопа опирается на ступеньку (-15 см),
- Правая — на полу (0 см).
Если бы таз не двигался вниз — левая нога бы "вытянулась", нарушив реалистичность. Этот код опускает таз вниз до уровня левой стопы, чтобы обе ноги оставались в пределах нормальной длины.
Смешаем кости с помощью полученных оффсетов
Modify Transforms (Модификация трансформаций)
- Что это: Это узел в Control Rig, который позволяет добавить смещение к текущей трансформации кости.
- Name : тут указываем какую кость мы хотим сместить
- Нода Get ZOffset_L содержить наше смешение кости + сглаживание котрое мы добавили в прошлвх шагах с помощью Alpha interpolate
- Mode: Additive Global: Этот режим означает, что смещение будет добавлено к текущей позиции кости в глобальных координатах мира.
Full Body IK (Инверсная кинематика всего тела)
Full Body IK (Инверсная кинематика всего тела)
- Это IK (Solver), который изменяет положение целой иерархии костей для достижения заданных целей ( короче говоря двигает цепочки костей) .
- pelvis (таз) — указывается началом цепочки . Solver будет изгибать всё, что "ниже" таза (ноги), и может даже слегка корректировать то, что "выше" (позвоночник), чтобы сохранить баланс( на самом деле этот солвер може тдвигать все тело) .
Effectors (Цели для IK)
Тут указываем
- 1: Кость foot_l (левая стопа) должна переместиться в позицию и принять трансформы от "виртуальной" кости IK_foot_L.
- : Кость foot_r (правая стопа) должна сделать то же самое, ориентируясь на IK_foot_R.
Позиции IK_foot_L и IK_foot_R — берем через Get transform - Bone
Вывод : мы измеряем расстояние до земли - если оно меняется - мы подстраиваем положение ног под эти изменения и коректируем таз с учетом этого , после этого создаем full body ik solver и кидаем трансформы c наших ik костей на эффекторы этого солвера и указываем уже кости foot_r and foot_l скелета как цель для этих эффекторов
Мой телеграм канал
В котором я рассказываю об анимации , разработке инди проекта ,и об unreal .