Как сделать управление персонажем в unity3d
Почему так часто используется передвижение через transform.position и почему это неправильно?
Как реализовать передвижение персонажа в Unity3d правильно?
Почему мой персонаж залазит в коллайдер другого обьекта при движении, хотя, вроде как, не должен?
Почему мой персонаж движется с разной скоростью если проседает FPS?
Почему используя присвоение в transform.position используют множитель Time.deltaTime ?
Почему двигать персонажа через смену transform.position неправильно?
Почему при использовании Velocity или .AddForce() не используется множитель Time.deltaTime ?
Все эти вопросы, фактически, являются одним единым вопросом, который слишком уж часто встречается у начинающих.
Заодно создал тэг unity3d-faq
Ответы (1 шт):
Хоть я здесь и разбираю в т.ч. нефизическое движение, я настоятельно рекомендую его НЕ использовать. И наоборот, я настоятельно рекомендую использовать ФИЗИЧЕСКОЕ движение.
В коде не должно быть прямой привязки к кнопкам. Должна быть привязка к параметрам Input Manager . Которые вы с легкостью можете найти в:
Edit -> Project Settings -> Input
Это хороший тон так делать. Удобнее менять все настройки клавиш из одного внешнего места, а не из многих документов с кодом.
Я буду использовать здесь 2 термина: "телепортация" и "плавное движение". В моем понимании:
Плавное движение - перерасчет позиции обьекта в рамках физики или паралельно физике на вызове FixedUpdate() .
Телепортация - перерасчет позиции обьекта на промежутке времени большем чем fixedDeltaTime .
- Плавное движение - исключительно физическое движение
Телепортация - изменение позиции вручную или использование .Translate() метода.
Учтите, что все что написано ниже упирается в верхние значения терминов, а не эти.
Двигать обьекты в игровых движках можно следующими способами:
используя физический движок (движение обусловленное физической моделью игрового движка)
движение НЕфизическое. Неправильный подход -- подход телепортации на каждом кадре. (в Update() )
движение НЕфизическое. Правильный подход -- плавное передвижение обьекта между кадрами (паралельно каждому просчету физики)
Движение реализуемое через CharacterController (здесь пока что не рассматривается т.к. новички в его сторону вообще не смотрят, может, позже распишу)
На практике метод передвижения подбирается под конкретного персонажа[персонажа -- не буквально. Это может быть и автомобиль]. В одном случае лучше будет физическое перемещение. В другом -- нефизическое. В третьем случае будет лучше всего CharacterController. Понимание что лучше в каком случае прийдет с практикой.
Новички очень часто использую телепортацию на каждом кадре, что есть критически неправильным подходом. Потом они упираются в какие-то артефакты поведения.
Например, могут проходить сквозь стены, видят дергающегося персонажа если подойти к другому обьекту с коллайдером или могут проваливатся под пол в отдельных случаях.
Нужно запомнить всего одно правило: Двигать/поворачивать через присвоение transform.position / transform.rotation нельзя. Это порождает проблемы. Прям в любом случае это вам вылезет боком.
Все для чего нужно это -- телепортация в другое место обьекта, но никак не его движение.
( на примере обьекта-шара )
Обратите внимание что за основу взят код из официальной документации/туториалов по юнити. Если есть несколько источников информации по какому-то мелкому но часто задаваемому вопросу (например движение персонажа ) -- выбирайте официальную документацию! Там точно фигни не посоветуют,
Есть Update() -- этот метод вызывается на каждой прорисовке кадра. Time.DeltaTime - это расчетное время между прорисовкой двух кадров. Если FPS проседает на компьютере, то этот параметр возрастает пропорционально проседанию.
Есть FixedUpdate() - это метод который вызывается при перепросчете физики. Time.FixedDeltaTime , как вы уже догадались, это время между вызовами FixedUpdate() . Оно может изменятся вручную через настройки, но упирается в физические возможности машины на которой игра будет запущена.
Если обьект не обладает физическими свойствами (не имеет RigitBody) эти параметры и методы можно использовать для НЕфизического передвижения.
Например поворот камеры.
Или крутящийся куб на небосводе.
Или движущийся изображение поезда где-то далеко, к которому нельзя подойти близко. Физика такому обьекту просто ни к чему -- это просто лишняя трата ресурсов
но, даже, в этом случае предпочтительно использовать Transform.Translate , но про это позже
Мы не получим дергающуюся картинку при проседании кадров если сделаем НЕФИЗИЧЕСКОЕ движение правильно:
ВАЖНО: . ПРИМЕР ВРЕДНОГО КОДА. Не делайте так!
мы присваиваем в новую позицию:
- старую позицию
- направление движения
- скорость передвижения умноженную на Time.deltaTime .
Поэтому, даже, если, у нас было 60 кадров и случилось проседание до 10 кадров -- скорость вращения/движения обьекта не будет изменятся. Ведь, мы ее учитываем вместе с проседанием кадров.
Допустим мы двигаем обьект через rb.Velocity или через AddForce() , то это физическое движение обьекта. То есть она может изменятся во времени сама под действием неких физических законов. Например, мы задумали сделать прыжок персонажа:
мы разово задаем вектор скачка. Только 1 долю секунды. Но он будет изменятся во времени автоматически равномерно уменьшаясь под силой тяжения. Пока не станет нулевым (верхняя точка прыжка), а потом не пойдет в минус по Y (падение), а потом не упадет на землю и не отскочит от нее (снова плюс по Y ) и так до полной остановки физической скорости обьекта на земле.
Допустим, мы двигаем изменением transform.Positon нашего плеера вперед по нажатию клавиши "пробел". В какой-то момент мы перестаем нажимать кнопку -- движение резко остановится и замрет. Это потому, что наше движение НЕ является физическим. Допустим мы подойдем к стенке и попробуем пройти на нее. Т.к. мы занимаемся телепортацией обьекта, то наш персонаж сначала дойдет до стенки, а потом телепортируется ВНУТРЬ нее, после чего Collider ее вытолкнет из себя. Как глубоко телепортируется внутрь зависит лишь от того, на какое расстояние мы телепортируем нашего персонажа за кадр. То есть это "Bad Practice" так реализовать перемещение персонажа.
Но в то же время есть и допустимое не-физическое перемещение. Это использование метода Transform.Translate() . Это уже НЕ телепортация обьекта. Это -- плавное перемещение обьекта (просто без учета физики). Но это не освобождает нас от использования deltaTime/fixedDeltaTime, как в примере оф.документации.
Если девайс с игрой сильно загружен, вызов методов Update() / FixedUpdate() тоже может просесть в скорости. И если в физике это учтено и без нас, то сейчас мы делаем НЕ физическое движение и именно по-этому это нужно учитывать добавлением даного множителя.
Но и без использования даного множителя у нас не появится проблем с провалами сквозь стены. Это просто фикс скорости.
Если в прошлом примере мы двигали шар, то было допустимо его толкать используя физ.модель. То есть мы использовали AddForce() для этих целей.
Допустим у нас персонаж -- человек, а не шар. Давай создадим вместо человека его подобие -- высокий куб 0.8х1.8х0.3 и попробуем нацепить на него наш скрипт движения шара. Выйдет следующее:
То есть когда мы пытаемся подвигать, наш персонаж падает (мы ж его толкаем, логично!). Когда он упал -- он не может двигатся из-за силы трения. Зато мы можем двигать его в прыжке. :)
Давайте актуализируем этот код под даного персонажа. Мы заменим физический толчек обьекта на не-физическое, но ПЛАВНОЕ перемещение обьекта в пространстве:
С этим кодом мы получим такой результат:
С такой реализацией у нас не будет проблем вроде скачков скорости на проседании или повышении количества FPS, проваливаний, дерганости, прохождения сквозь стены или других неожиданностей.
Теперь мы можем занятся украшательствами -- например повороты тела. Довольно приятно реализованы повороты вот здесь: Как сделать управление, как в игре "Overcooked"?
Так же можно добавить анимацию бега на нашего персонажа (ну если бы это был не куб).
Да, можно подобное реализовать и на физике.
Наша прошлая версия скрипта имела несколько недостатков. А именно:
- нужно было вручную отмечать каждый из предметов от которого мы можем прыгать. То есть добавив ящик на пол, нам нужно еще и его отметить тэгом Ground.
- если поставить кучу ящиков вертикально, присвоить каждому из них тэг "Ground", то просто подойдя к вертикальной стене из ящиков мы сможем взлететь вверх). То есть нам не важно к чему мы дотрагиваемся -- к полу или к стене -- оно давало нам возможность прыгать.
- наше движение все так же было НЕ физическим. То есть если мы начнем двигать игрока влево-вправо то он будет резко останавливатся а потом резко двигатся в противоположную сторону. В живом мире так не бывает.
Вспомните уроки физкультуры, когда нужно было пробежать 30 метров вперед, взять палочку, пробежать 30 метров назад, положить палочку и еще раз 30 метров в другую сторону. Что случалось с бегуном в этот момент если посмотреть сбоку? Сначала скорость растет, потом достигает пика, а потом торможение, взятие палочки, бег в другую сторону -- снова возрастание скорости. Никаких резких скачков. Этого можно добится именно передвижением при помощи физики.
Давайте поместим на наш куб CapsuleCollider (минимальное торможение из-за силы трения) и заблочим в rigitBody rotateX и rotateZ (что б наш персонаж не падал на бок).
А потом нацепим на него вот этот скрипт:
Вы видите эту плавность, как будто человек бежит, останавливается, бежит в другую сторону? Красота!
А теперь вернитесь к прошлой гифке и присмотритесь. Движение совсем не такое :) Там как буд-то рукой двигают шахматную фигуру по доске.
Ну и описанные выше баги поведения были пофикшены с такой реализацией.
Можно добавить еще физический материал нашему персонажу и откоректировать его поведение.
Вообще улучшать реализацию можно до бесконечности. Но, думаю, основные проблемы СПОСОБОВ ПЕРЕДВИЖЕНИЯ с которыми вы столкнетесь, я затронул :)
Такая физика чаще используется для неживих персонажей. Например для автомобилей.
Одним из моих любимейших примеров нестандартной физики движения является игра Ori and the Blind Forest
Такое перемещение/такие прыжки невозможно сделать на основе физики. Это делалось через нефизическое перемещение + костыли для получения нужных эфектов.
Сначала разрабатываются концепты движения. Они делаются в любом видеоредакторе с примитивными фигурами. Вот пример (если станет недоступным искать можно по Ori and the blind forest Enemy Concepts ) :
Обратите внимание на то, то здесь прорисовано не только перемещение обьекта, но и его вытягивания/сжатия. Изменения формы во время любого взаимодействия с внешним миром. В т.ч. выстрелы так же влияют на форму. А так же что указываются радиусы опознавания главного героя каждым отдельным врагом.
Когда вся концепция всех движений готова - делается нефизическое движение обьекта и приближается разного рода костылями к концепту игры.
Костыли для каждого персонажа/врага свои собственные. Это делается что бы каждый из них обладал своей уникальной физикой. Сделать это на общей физике навряд ли возможно.
ДАЖЕ если вы реализовали физическое передвижение вашего персонажа, все равно может случится такое, что просчет CollisionDetect может проходить с ошибками. Это редкость, но такое бывает иногда.
Для таких случаев есть настройки отвечающие за обработку CollisionDetect в настройках самого RigitBody.
Делать такое нежелательно т.к. это негативно сказывается на производительности. Так что считайте это, скорее, спасательным кругом, чем панацеей.
Не так давно в Unity зарелизили новую систему управления, а значит самое время посмотреть на неё поближе.
Unity не только активно развивающийся, но и очень активно изменяющийся продукт. Замена рендер пайплайнов, UIElements, New Input System - всё это изменения последнего времени, которые призваны сделать движок ещё более быстрым, гибким и дружелюбным. История знает много примеров, когда компании предпринимали рефакторинг больших систем внутри своих продуктов, результатом таких изменений становились как новые успехи в их развитии, так и крах. Отбросив печальные размышления на эту тему, посмотрим, чем же новая система отличается от старой.
На смене поколений
Новая система управления это довольно заметное событие в мире Unity, комьюнити встретило её с очень большим энтузиазмом, обычно приговаривая, что текущая версия не очень удобна. Да и сама компания изготовитель разделяет это мнение и заявляет, что старая система была разработана до добавления большого количества поддерживаемых устройств и не очень была на них рассчитана. В результате интернет содержит довольно большое количество обзоров, которые обычно показывают настройку базового окна нового Action Asset, его сразу можно узнать по трём большим, горизонтально расположенным, блокам настроек. Мы же попробуем пойти в обратном направлении и сначала разберёмся в базовых элементах новой системы, а от них перейдём к более высокоуровневым.
Документация
Как ни странно, для такого нового пакета, у него довольно хорошая документация, которая всегда содержит в себе ответы на возникающие вопросы, так что сразу приведу на неё ссылку, в том числе и по причине наличия ограничений, которые нужно учитывать в случае её использования. Отмечу часть с вопросами и ответами, ознакомление с ней сильно упростит ваши первые шаги.
Установка
Так как пакет с новой системой управления вышел в релиз его легко найти в Package Manager поиском по названию Input System .
Во время установки вас уведомят о том, что у вас выключен native platforms backend и ничего не будет работать, пока вы не переключитесь на него, потеряв при этом доступ к текущему API.
Не очень понятно зачем они так пугают неокрепшие умы, так как в настройках Edit > Project settings… > Player > Other Settings > Active Input Handling* есть возможность включить сразу оба. Так что не очень важно как вы ответите на вопрос про отключение, вы можете сразу переключить backend в любое подходящее вам значение. =)
Встроенные примеры
После установки пакета появится доступ к приличному набору примеров по использованию новой системы, который содержит всё необходимое начиная от простых примеров и заканчивая добавлением управления на экран смартфона или перенастройки управления в рантайме.
Архитектура
Система настолько широка, что все её настройки рассмотреть довольно проблематично, да и не нужно, документация покрывает все необходимые для начала моменты.
Если же описать архитектуру в двух словах, то она состоит из 3х уровней:
- Нативный бэкэнд - предоставляется текущей платформой и фактически не является частью новой системы ввода
- Низкоуровневый слой - обменивается с бэкэндом информацией в виде эвентов и необработанных данных и сильно заточен на оптимизацию работы с памятью и производительность
- Высокоуровневый слой - представляет низкоуровневые данные в удобном для настройки и использования виде
Отдельно стоит отметить, что новая система полностью построена на эвентах и всячески подталкивает к их использованию.
Input.GetMouseButtonDown(0)
Думаю, что не многие настраивают управление в начале разработки или при тестировании очередной механики, поэтому первым делом хотелось бы узнать, как отловить обычный клик мышки из кода. В новой системе вызов Input.GetMouseButtonDown(0) превратился в Mouse.current.leftButton.wasPressedThisFrame , как можно заметить количество символов немного увеличилось, с другой стороны, теперь можно не вспоминать, под каким индексом идёт левая кнопка, а если автодополнение в вашей IDE понимает чего вы хотите, то разница будет совсем незначительной. Такой же подход используется для доступа к клавиатуре, например, отпускание кнопки пробел на клавиатуре Keyboard.current.spaceKey.wasReleasedThisFrame .
InputAction
Использование прямого доступа к кнопкам не является основным методом работы с новой системой. Базовым понятием в ней являются объекты типа InputAction, по сути, это абстракция над источниками событий(кнопки, стики и т.п.), которая предоставляет данные об их состоянии(нажата ли кнопка или направление стика) и с помощью эвентов оповещает об их изменении. Лучше всего относиться к ним как к логическим элементам(прыжок или выстрел) и не привязываться к физическим свойствам, таким как нажатие кнопки.
Пример вида, добавленного в компонент InputAction:
Настройка InputAction предоставляет выбор таких параметров:
Action Type может быть трёх типов:
- Value - стандартный тип, используется для любого типа ввода, постоянно отслеживающий состояние устройств
- Button - отличается от Value тем, что может быть связан только с кнопками и используется для отслеживания изменения состояния
- Pass-Through - в отличие от других типов не используют схему started-performed-canceled(основные типы эвентов) и фактически всегда находится в состоянии performed, его удобно использовать в случае необходимости обработки всех данных с нескольких источников событий
Control Type - описывает тип данных предоставляемых устройством, например, в случае со стиком можно получить данные в виде структуры Vector2.
Interactions - предоставляют возможность настройки специфических действий, допустим, долгого нажатия или мультиклика.
Processors - добавляют постобработку данных поступающих от контроллера перед выдачей их логике, например, нормализацию вектора направления стика на контроллере.
В зависимости от выбранных настроек предоставляется доступ к разным физическим устройствам, способным предоставить необходимые нам данные. В качестве примера кнопка мышки способна обрабатывать только клики, и, в случае выбора предоставления данных в виде вектора, не может быть использована в качестве отслеживаемого средства ввода.
Также предоставляется доступ к нескольким композитным устройствам, например, направление движения можно получить в виде вектора, получаемого при помощи четырёх кнопок(WSAD или другой комбинации). Набор композитных устройств можно дополнить при необходимости своими, подробнее об этом можно прочитать в документации.
Использование InputAction не требует каких-то дополнительных сущностей и вполне подходит для использования в компонентах, только не стоит забывать, что при создании они находятся в выключенном состоянии и требуют отдельного включения через вызов метода Enable() .
Action Maps
Это объединение нескольких InputAction, которое отвечает за разные наборы действий в игре. Допустим, в меню, с помощью стика на контроллере, вы перемещаетесь между разными кнопками интерфейса, а в игре стик отвечает за перемещение персонажа.
Control Schema
Это абстракция над InputAction которая позволяет задавать разные триггеры для этих самых действий в зависимости от используемых физических устройств. Допустим, управление передвижением с клавиатуры осуществляется через WSAD, а с контроллера через левый стик.
Action Asset
Это новый тип ассета, который отвечает за комплексную настройку InputAction, ActionMap и схем управления, именно его можно встретить в виде большой панели из трёх блоков в большинстве других обзоров.
Итого
Фактически вся новая система вертится вокруг наборов InputAction, а всё остальное призвано структурировать работу с ними. В результате можно выделить четыре основных подхода к использованию новой системы:
- Обращение к данным устройства напрямую - как в случае с Mouse.current.leftButton.wasPressedThisFrame
- Использование базовых InputAction
- Генерация класса с набором InputAction из Action Asset, что сильно упрощает настройку сложных систем управления, использующих разные схемы
- Использование Action Asset через объект PlayerInput
Как можно заметить Action Asset вовсе не является необходимым условием для настройки управления и служит лишь для упрощения работы с действительно большими и сложными решениями.
Изменение управления
В предыдущей статье мы рассматривали шаблон “Команда”, который обычно используют для добавления возможности перенастройки управления в игре. Использование этого подхода в новой системе фактически добавит лишний слой абстракции над InputAction, так как они уже являются логическими элементами. В свою очередь, изменение управления становится не очень очевидным и реализуется через класс с подозрительным названием InputActionRebindingExtensions. По этой теме есть отдельный пункт в документации и довольно сложный пример под названием Rebinding UI, который поставляется с пакетом. Так как это очень важный элемент для системы управления, то мы рассмотрим его минималистичную реализацию ниже.
Практика
Примеры с полноценным созданием Action Asset довольно часто встречаются на просторах интернета и не имеет смысла повторять их ещё раз, так что, в качестве минималистичного примера, изменим управление магом из наших предыдущих статей на использование новой системы с применением InputAction, а также добавим возможность перенастройки управления.
Реализация
Для базового использования InputActions не требуется какой-либо дополнительной настройки кроме добавления кнопок
Результат
Для первого запуска заклинания используется левая кнопка мышки, а второй выстрел происходит после перенастройки действия на кнопку клавиатуры f
Заключение
Изначально работа с новой системой вызывает ассоциации с добавлением кастомного редактора на какой-нибудь компонент, как, например, в нашей статье о редакторе цветов для генератора Шума Перлина. Но понимание что это очень большое изменение текущего подхода и переход на совершенно новое api приходит очень быстро. Большой набор возможностей и новых компонентов может отпугнуть, но довольно неплохая для первой версии документация и примеры позволяют надеяться на быстрое погружение для её полноценного использования, если, конечно, текущие ограничения не являются для вас большой преградой. Надеюсь, эта статья немного прояснила для вас основы работы с New Input System. Пока! =)
Создаем скрипт PlayerControl
Чтобы всё работало как надо, персонажу нужно придумать и назначить отдельный слой. Это нужно для того, чтобы работал Raycast в скрипте, который определяет возможность прыжка и в тоже время для того, чтобы любой другой Raycast, мог взаимодействовать и игроком.
Всё достаточно просто. Различные детали, каждый сможет настроить под себя, плюс можно еще сделать материал для физики тела, например, чтоб увеличить коэффициент трения или наоборот, изменить массу Rigidbody, ну и прочее. В общем, поэкспериментируйте с настройками.
По идеи не совсем то, по какой-то причине персонаж начинает вращение и не прекращает
Ладно, давайте упростим задачу до безобразия:
При нажатой кнопки W персонаж меняет свой вектор на вектор камеры, таким образом передвигается по направлению камеры, в ином случае, т.е. когда W не нажата, персонаж покоится а камеру можно вращать вокруг него.
Kejikeq
> Вопрос - как сделать так, чтобы персонаж передвигался относительно клавиши W,
> то есть условно a,d поворачивали персонажа, а W передвигала бы его прямо, а так
> же, требуется чтобы персонаж делал проверку на то куда смотрит камера и
> разворачивался в её сторону плавно. Сама камера сделана через lookat и
> привязанна к пустышке внутри персонажа.
То есть у тебя камера внутри персонажа, делает look at на персонажа, вращается вслед за персонажем, а персонаж должен вращаться вслед за камерой?
И после этого ты удивляешься, что вращение не прекращается?
Предлагаю вытащить камеру из персонажа для начала, а потом погуглить Cinemachine
Increaser
Ну а как привязать камеру к персонажу без привязки ._.
Kejikeq
> Ну а как привязать камеру к персонажу без привязки ._.
Increaser
> погуглить Cinemachine
Increaser
Мне начинает казаться что вся проблема заключается в том, что я хочу чтобы камера могла свободно вращаться вокруг персонажа и при этом следовать за ним а он мог поворачиваться за камерой, а по идеи должно происходить наоборот, камера должна поворачиваться в зависимости от того куда смотрит персонаж и двигаться за ним, ну а уж если мне хочется чтобы она свободно вращалась вокруг персонажа, то скорее всего следует сделать отдельную кнопку при которой камера перестает следовать за персонажем и становится свободной, наверное. Я запутался.
zeffyros
Так в Cinemachine те же настройки, loot at и т.д. да функционал шире, но тем не менее.
zeffyros
Та я глянул, тут видишь как у него настроено, его персонаж повернулся, камера повернулась за ним, но вращать камеру вокруг персонажа он не может, так как камера строго следит ему в затылок условно, а мне то нужно другое.
>Kejikeq
Вот несколько вариантов слежения камеры за персонажем, все работает, лично проверял. Если что-то не работает, значит не так сделано.
Ссылка
Та я глянул, тут видишь как у него настроено, его персонаж повернулся, камера повернулась за ним, но вращать камеру вокруг персонажа он не может, так как камера строго следит ему в затылок условно, а мне то нужно другое.
Так сделайте
- найти формулу поиска точки на окружности с заданным радиусом
написать скрипт
- если не нажата клавиша (у вас вперед собственно) но нажата такая-то
тогда
- отодвинуть камеру от персонажа на нужное расстояние (это будет радиус)
- найти следующую точку куда подвинуть камеру (то есть вы хотите на такой-то угол повернуть. ищете точку с этим углом) (оно там в радианах вероятно)
- делаете transform.position, например в эту точку
- делаете поворот камеры по направлению: у вас есть 2 точки сама камера и центр, направление то есть известно. (от камеры к центру)
- повторить операцию пока нажата клавиша.
(это не экспертное мнение и скорее всего все можно проще значительно, просто я бы как-то так бы делал бы, но я сам только разбираюсь, а потом бы разбирался бы есть там какой-то функционал в unity для вращения вокруг центра или нет, вероятно есть)
там формулы что то типа:
test.x = BeginPosition.x + Mathf.Sin(RotationY * Mathf.Deg2Rad) * Width / 2f;
так же надо для Z но там еще одна формула похожая
Kejikeq
> я глянул, тут видишь как у него настроено, его персонаж повернулся, камера
> повернулась за ним, но вращать камеру вокруг персонажа он не может, так как
> камера строго следит ему в затылок условно, а мне то нужно другое.
На 4:10 не то, что ты хочешь разве?
Unity анимированный игровой 3d персонаж.
Создайте качественного, полностью анимированного 3d персонажа, управляемого при помощи кнопок или при помощи джойстика на мобильном устройстве.
Чему вы научитесь:
Вы сможете взять любую 3d модель персонажа, добавить любые анимации, импортировать все это в Unity и превратить в полноценного игрового персонажа. Вы сможете управлять своим героем с клавиатуры, а также на экране мобильного устройства.
Для кого этот курс:
Курс предназначен для новичков. Основная задача, решаемая в курсе: очень быстрое создание и внедрение в игровой проект трехмерного анимированного персонажа.
Знакомство с программой Unity3d необязательно, все рассмотрим в курсе.
Дистанционное обучение аналогичное очному. Связь с ментором, персональный разбор домашних заданий, создание полной итоговой работы.
Читайте также: