Цель статьи - перенести персонажа из Makehuman в Unity3d так, чтобы его одежду можно было снимать и надевать прямо во время игры.
Для этого нам понадобится Makehuman, Blender3d, Unity3d и его плагин UMA (они все бесплатные). Статья написана по мотивам этого ютуб канала, повторяя за автором я набил много шишек, и теперь готов изложить своё видение.
Этап 1: Создание персонажа в Makehuman
Это самый легкий и приятный этап, тут необходимо смоделировать персонажа. Makehuman довольно простая программа, поэтому не буду описывать, как в ней работать.
Но есть три важных момента. Во-первых: нужно добавить скелет к модели (добавляется во вкладке Pose/Animate). В этом туториале я использую риг Game Engine. Во-вторых, если на персонаже есть одежда, то нужно отключить опцию удаления полигонов под одеждой (это можно сделать во вкладке Geometris -> Clothes, и снять галочку Hide faces under clothes). В-третьих, нужно экспортировать в fbx и указать единицы метры. Так же, на всякий случай, можно сохранить модель.
Несколько дополнительных моментов
Не надо менять позу персонажа.
Одежду можно экспортировать по частям. То есть не надо напяливать все шмотки сразу, можно, например, сначала сохранить персонажа, у которого только штаны с рубашкой. В блендере экспортировать их, затем вернуться в makehuman, снять старую одежду и повторить операции экспорта, например, для шляпы и ботинок.
Единицы измерения метры, значит что десять клеточек в makehuman будут означать условный метр
Этап 2: Обработка его в Blender3d
Тут нам нужно сделать три вещи:
Нормализовать модель
Добавить глобальную кость
Нарезать части тела
Запускаем Blender3d. Для начала нам нужно удалить свет, камеру и куб и импортировать нашу модель. Затем импортируем нашу модель: File -> Import -> fbx (и выбираем наш fbx файл)
Грабля на которую я наступил
Первый раз когда, потратил время на создание персонажа makehuman, в блендере нажал на экспорт вместо импорта (в результате в мой fbx файл записалась пустая сцена, и пришлось заново создавать персонажа). Тоже самое касается импорта.
Нормализация
Персонаж импортируется не в своей дефолтной позе. Если мы например, с нуля смоделируем персонажа, затем зададим ему кости, то его дефолтная поза будет той, в которой мы его смоделировали. И если мы изменим ему позу при помощи костей и перейдем в режим редактирования, то сетка персонажа примет его дефолтную позу. Наша задача очистить трансформацию позы.
Очищаем трансформацию позы
Переходим в блендере в режим позы
Выделяем всё, (клавиша a)
Затем нажимаем pose ->clear transform -> all
Чтобы проверить, что трансформации очищены, можно перейти в режим редактирования. Модель не должна при этом измениться.
После этого персонаж развернулся на 90 градусов, нужно вернуть его обратно
Вращение персонажа в блендер
Сначала нужно перейти в объектный режим.
Напоминаю что мышь должна находиться на экране с моделькой. Далее нужно нажать R для перехода в режим вращения, затем X для того чтобы вращение было только по этой оси. Затем на клавиатуре набрать -90 и нажать Enter
И наконец, нужно очистить внутреннее масштабирование и вращение всех мешей.
Очистка масштабирования и вращения
Если мы, например, создадим два куба и первый сожмем в объектном режиме, а второй в режиме редактирования, то они сожмутся по разному. На панели трансформации в первом случае scale по всем осям будет 0.500, во втором 1.000. Это значит, что у первого куба меняется атрибут scale, а сам куб, как бы не меняется. То же самое с вращением.
Для модели нашего персонажа нам нужно добиться чтобы все его меши имели вращение 0° и масштабирование 1.000 (без изменения формы самих мешей естественно).
Для этого нужно, в объектном режиме выделять каждый меш (включая арматуру) нажимать на ctrl + a, и выбирать пункт rotation & scale.
Добавление глобальной кости
Теперь нам нужно добиться, чтобы скелет был совместим с UMA. Для этого нужно добиться такой иерархии костей.
Global (Head= 0,0,0 Tail=0,0,0.1) // новая кость
Position (Head= 0,0,0 Tail=0,0,0.1) // бывшая Root кость
весь старый скелет (кость pelvis)
Пошаговая инструкция как этого добиться
Выделим Root кость и переименуем её в Position. Затем выставляем у неё характеристики Transform так же как на картинке.
Далее выделяем в арматуру (у меня это Game_engine) и переходим в режим редактирования. Далее нажимаем на add -> single bone
У нас появится кость с именем bone, и её нужно переименовать в Global и выставить в ней те же характеристики, что и для кости Position.
Далее нужно сделать Global кость предком кости Position. Для этого нужно сначала свернуть список дочерних костей у кости Position.
Далее выделить кость Global, затем зажав shift, выделить кость Position. Перевести мышь на экран с 3d моделью и нажать на ctrl + p, в выпадающем меню выбрать keep offset.
Нарезка персонажа
Персонаж в UMA состоит из слотов - это такие части модели на которые можно надевать/снимать какую-нибудь шмотку. Например, когда мы надеваем броню на торс персонажа, у него должен исчезнуть торс и замениться торсом с доспехами.
В этом туториале мы разобъём персонажа на следующие слоты
Голова
Торс
Ноги (без ступней)
Ступни
Глаза
Волосы
Первом делом нам нужно создать сетку швов (seams mesh). Для того чтобы можно было менять те части, которые идут единой сеткой (например чтобы голова выглядела приделанной к туловищу, а не как отдельная моделька). Для этого нам нужно продублировать главную сетку.
Создание seams mesh
Выделяем главную сетку (в моём случае она выглядит вот так). Прочие сетки (глаза, волосы и одежду) я скрыл.
Нажимаем shift + d, затем RMB
В результате она должна продублироваться.
И называем её seams mesh (либо любым другим названием).
Теперь осталось добиться того, чтобы вместо старого меша были отдельные части.
Нарезка персонажа
Переходим в режим редактирования нашей главной сетки (не seams mesh).
В подрежим редактирование поверхностей.
Зажимаем alt и нажимаем на какой нибудь из прямоугольников на шее чтобы выделить полоску как на рисунке ниже (стараемся кликнуть ближе к вертикальному ребру чем к горизонтальному, иначе выделится вертикальная лента).
UPD: раньше выделял голову при помощи кругового выделения (клавиша c) и рентгеновского вида, но пользователь ValeryIvanov подсказал более удобный способ:
Нужно скрыть это кольцо (клавиша h), далее навести курсор на голову и нажимаем L (должна выделиться вся голова), затем снова показываем полосу на шеи, нажав на Alt + L. Далее нажимаем на P и в выпадающем меню выбираем SПelection. Всё, голова отделена.
Не забудем переименовать получившийся меш.
Теперь такую же операцию нужно проделать с другими частями. В результате у меня получилась вот такая картина. Тут поменял ракурс и выделил торс и ступни чтобы было лучше видно меши на которые я разбил модель.
Ещё я нарезал одежду и переименовал части тела.
Таким образом, мы имеем seams mesh и множество мешей если собрать которые получиться модель персонажа. Каждый с одинаковой арматурой.
Теперь экспортируем персонажа в формате fbx (желательно в ту же папку куда экспортировали из makehuman потому что там должны лежать текстуры к нему)
Этап 3: Создание UMA расы
Подготовка сцены
Открываем unity, скачиваем вот этот ассет и импортируем его в unity. Это ничто иное как UMA - Unity Multipurpose Avatar, фреймворк который позволяет кастомизировать персонажей. Перетаскиваем префаб UMA/Getting Started/UMA_GLIB в иерархию.
Импорт персонажа
Создаём папку в юнити в которой будем работать, я назвал её characters. Перетаскиваем туда папку с нашим персонажем (fbx и текстуры). Возможно появиться сообщение о том, что некоторые текстуры не помечены как карты нормалей. Можно нажать fix now.
Для удобства при работе с UMA я закидываю всё в одну папку (в characters), потому что при создании и настройки ассетов постоянно приходиться указывать в них ссылки на друг друга. А каждый раз лазить по папкам не всегда удобно. В любом случае, после того как мы всё настроем можно будет навести порядок.
Выделяем в менеджере проекта нашу fbx модельку, в инспекторе снимаем галочку Convert Units, и нажимаем Apply. Далее переходим во вкладку rig в animation type, выбираем Humanoid и так же нажимаем Apply.
Теперь нажимаем в верхнем меню UMA -> Extract T-Pose (в менеджере проекта наша fbx модель должна быть выделена). В результате должна появиться папка TPoses с экспортированной т-позой.
Скриншоты
Создание слотов и оверлеев
В верхнем меню выбираем UMA -> Slot Builder, появившийся окно я перетаскиваю рядом со вкладкой иерархии. Нажимаем на стрелочку рядом с fbx моделью и находим там часть seams mesh и перетаскиваем её в поле seams mesh в Slot Builder. В UMAMaterial выбираем UMA_defuse (для простоты). В slot destination folder переместите папку куда будут генерироваться слоты.
Теперь перетаскиваем части которые должны выглядеть единым мешем в панель automatic Drag and Drop porcessig. Это голова, торс, ноги и ступни (но не глаза и волосы). После того как закончили, в seams mesh выберите None и подобным образом перетащите глаза, волосы и одежду.
Скриншоты
Теперь нужно создать оверлеи. Оверлей это по сути текстура, созданная специально для UMA, которую можно комбинировать с другими такими текстурами, используется например для добавления шрамов, татуировок, макияжа, рисунка на щите (ещё можно добиться чтобы цвет этого рисунка на щите менялся программно). Итак, правый клик мыши в менеджере проекта, Create -> UMA -> Core -> Overlay Asset. В Overlay name впишите имя оверлея (например skin), в material выберете тот материал который указывали при создание слотов (в нашем случае это UMA_defuse) в спойлере количество каналов укажите 1, и перетащите в появившиеся поле _MainTex соответствующую текстуру. Ту же операцию проделайте для других текстур.
В верхнем меню нажмите UMA -> Global Library, и перетащите в левую панельку папку в которой мы работали. Это добавить в глобальный индекс все созданые нами вещи. Ничего страшного если мы не сделаем этот шаг, в таком случае, пердложения добавить расу/слот/оверлей в глобальный индекс, будут показаны при настройке расы и базового рецепта.
Скриншоты
То же самое проделайте для глаз, волос и одежды. По завершении, оверлеи лучше перенести в рабочую папку.
Создание TextRecipe и RaceData
Снова правый клик мыши в менеджере проекта Create -> UMA -> Core -> Race Data, затем Create -> UMA -> Core -> Text Recipe. Первый файл - это файл расы. Второй - это базовый набор слотов/оверлеев для неё. Придумайте название для них и переименуйте файлы соответствующим образом. Выделите расу и, сначала, в поле Base Race Recipe перетащите рецепт который мы только что создали. В поле Race Name введите её название, в TPose перетащите т-позу которую мы получили ранее.
Теперь нужно назначить Wardrobe Slots, это что-то типа ячейки инвентаря, куда можно надеть шмотку. В них помещается Wardrobe Recipe. Wardrobe Recipe по сути это сама шмотка. В чем же его отличие от обычный слотов? Слот это сменяемая одна из частей модели, вардроп рецепт это информация о том как этот слот (шмотка) будет надеваться на тело. Например если есть шляпа, то слот шляпы будет содержать меш шляпы, (и информацию о том, оверлеи с каким материалом с ним совместимы). А Wardrobe Recipe будет содержать ссылку на этот слот, нужные оверлеи, и информацию о том что нужно убрать волосы (и другую шляпу если она есть), и ещё скрыть часть головы, если её части проходят сквозь шляпу. Поэтому в Wardrobe Slots можно создать примерно вот такой список:
None
Hair
Head
Body
Legs
Feet
Теперь выделите файл с BaseRecipe, переключитесь на вкладку Slots. В поле Race Data перетащите наш файл расы (да, теперь файл расы и базовый рецепт ссылаются друг на друга). Теперь нужно перетащить слоты тела на соответствующую панель (слоты одежды не обязательно перетаскивать). В результате должен получиться список из слотов. Теперь для каждого слота нужно перетащить соответствующий оверлей. В данном случае для всех частей тела используется один и тот же оверлей, и после перетаскивания он будет отображаться в панели shared overlays.
Скриншоты
Я назвал их MaleRace и BaseRecipe соответственно
Добавление персонажа на сцену
Всё что мы до этого делали было подготовкой к этому шагу. Настраиваем сцену (например добавляем плоскость, играющую роль земли). Перетаскиваем префаб UMA/Getting Started/UMADynamicCharacterAvatar в сцену (можно переименовать его). В инспекторе в компоненте Dynamic Character Avatar в поле Active Race выбираем нашу расу.
Добавляем анимацию
У меня по умолчанию не запустилась анимация (для базовых рас тоже, поэтому подозреваю что это недоработка). Глубоко этот вопрос пока не изучил, но сумел добиться чтобы она воспроизводилась. Для этого под спойлером Race Animation Controllers в списке Race Animators удаляем все элементы и добавляем новый, в Race указываем нашу расу, в Animator выбираем IdleTest-w-head.
Нажимаем на Play. У вас должен появиться персонаж которого мы собрали.
Скриншоты
Добавление одежды
Теперь создадим одежду Create -> UMA -> DCS -> Waredrop Recipe, выделяем созданный ассет назначаем ему расу, задаём имя и назначаем Wardrobe Slot . Затем по аналогии с созданием базового рецепта, перетаскиваем на панель слот и оверлей той шмотки которую мы ходим создать. Затем перетаскиваем этот ассет в глобальную библиотеку, так же как мы делали ранее. Проделываем эту операцию для других шмоток и волос. Теперь выделяем нашего персонажа в иерархии, в спойлере Customization -> Default Recipes перетаскиваем созданные вардроп рецепты на панельку.
Если тело проходит сквозь одежду, то нужно создать сетку сокрытия. Create -> UMA -> Misc -> Mesh Hide Asset, указываем слот с частью тела, который нужно частично скрыть, нажимаем на кнопку Begin Editing и в редакторе выделяем те грани, которые будут скрываться при надевании этой шмотки. Далее в Waredrop Recipe нажимаем на кнопку Add Mesh Hide Asset, и выбираем сетку сокрытия.
Теперь можно надевать и снимать эту вещь. Для этого выбираем наш Dynamic Character Avatar, и в спойлере Customisation -> Default Waredrop Recipes перетаскиваем на панельку наш вардроп рецепт.
Скриншоты
На всякий случай скажу что если надеть их не в игре, а в режиме редактирования, то их не нужно будет каждый раз заново надевать.
Сетка тела, может в некторых местах проступать через одежду. Есть два варанта как поступить: назначить в wardobe recipe слот (слоты) которые будут скрываться при применение этого рецепта. Или можно добавить сетку сокрытия.
В случае на скриншоте можно просто скрывать весь слот
Но если одежда покрывает не весь слот (то есть скрыть слот не варант) то на помощь придет сетка сокрытия.
Альтернативный способ, это сразу перенести слот части тела, которую нужно скрывать этой сеткой сокрытия, в поле Slot Data Asset, в моем случае это ноги (не шатаны).
Запустив игру и надев нужную деатль одежды (в нашем слчае штаны), мы теперь увидим что они не просвечивают.
Добавление и удаление одежды программно
Для этого нужно использовать методы компонента DynamicCharacterAvatar. Для добавления SetSlot и ClearSlot для удаления, после этого нужно вызвать метод BuildCharacter. Первый аргумент SetSlot это имя слота куда необходимо надеть шмотку. Полный список доступных слотов можно посмотреть в файле расы. Второй аргумент это имя файла нашего Waredrop Recipe. В ClearSlot нужно использовать только имя слота.
Первый аргумент в SetSlot излишен (имхо)
На мой взгляд, информация о том куда мы надеваем шмотку излишняя. По сути, значение первого аргумента SetSlot всегда совпадает с полем Waredrop Slot соответствующего Waredrop Recipe.
Вот пример скрипта, вам остается куда куда-нибудь повесить методы AddWardrobe и RemoveWardrobe.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UMA;
using UMA.CharacterSystem;
public class Program : MonoBehaviour
{
// сюда нужно перетащить наш Dynamic Character Avatar
public GameObject DCA;
private DynamicCharacterAvatar avatar;
void Start(){
avatar = DCA.GetComponent<DynamicCharacterAvatar>();
}
public void AddWardrobe(string wardrobeSlot, string wardrobeRecipe){
avatar.SetSlot(wardrobeSlot,wardrobeRecipe);
avatar.BuildCharacter();
}
public void RemoveWardrobe(string wardrobeSlot){
avatar.ClearSlot(wardrobeSlot);
avatar.BuildCharacter();
}
}
Заключение
Спасибо что дочитали до конца, надеюсь, эта статья станет для вас ещё одним шагом к созданию своей игры мечты.
kokorins
Серьезно? Ни одной картинки?!
Mingun
Почему же ни одной… Под спойлерами есть парочка, но согласен, картинок можно было бы и побольше. К концу автор явно разленился
Faydaen Автор
Спасибо за замечание. Добавил картинок