Передвижение персонажа в Unity 2D и 3D
Приветствую! В данной статье мы разберём правильную реализацию движения персонажа. Поскольку движение 2D и 3D персонажей почти на 100% эдентичны, то мы поочереди их и разберём. Благодаря чему, начинающий разработчик не только разберётся в том, как реализовать функцию передвижения, но увидит разницу между движениями 2D и 3D.
Начнём свой пусть с 2D передвижения, поскольку он чуток легче в понимании.
Передвижение 2D персонажа
Первым делом создадим игровой объект нашего персонажа, и назовём его, например, Player.

Далее добавим к нашему персонажу компонент Rigidbody 2D. Если в Вашей игре отсутствуют законы гравитации, то в в поле Body Type необходимо указать значение "Kinematic".
P.S. Обычно гравитация отсутствует в 2д играх с видом сверху.

Теперь самое интересное, нам необходимо создать C# скрипт с названием, например movePlayer, и присвоить этот скрипт нашему объекту Player. А сам скрипт должен иметь следующее содержимое:
Готово! Давайте разберём наш код. В строках 7,8,9 мы создали 3 переменные:
- rb — которая будет хранить ссылку на компонент Rigidbody2D
- speed — скорость передвижения вашего персонажа
- moveVector — направление движения персонажа в виде вектора
Далее в 13 строке мы в переменную rb присваивает ссылку на наш компонент Rigidbody2D, чтобы в дальнейшем можно было бы работать с его свойствами и методами.
В строке 18 в переменную moveVector.x мы записываем значение движения по горизонтали. Если максимально простыми словами, то при нажатии на клавишу "D", в переменной записывается значение "1" — вперёд. При нажатии на клавишу "A" — в переменную записывается "-1" — назад.
Аналогичная ситуация происходит и в 19 строке. При нажатии на клавишу "W", в переменной записывается значение "1" — вверх. При нажатии на клавишу "S" — в переменную записывается "-1" — вниз.
Ну и в 20 строке, с помощью метода MovePosition, мы заставляем двигаться нашего персонажа, исходя из значений которые мы получили в moveVector.
Теперь Ваш персонаж может спокойно передвигаться в мировом пространстве. Как видите, всё очень просто и понятно. Теперь как и обещал, перейдём к 3D.
Передвижение 3D персонажа
Для начала, создадим игровой объект персонажа с названием, например, Player. А так же создадим объект Земли, по которой персонаж будет передвигаться. И назовём его, например, Ground.

Так же добавляем к персонажу компонент Rigidbody — чтобы на него действовала гравитация(если нужно).
Теперь так же необходимо создать C# скрипт с названием, например movePlayer, и присваиваем этот скрипт нашему объекту Player. А сам скрипт должен иметь следующее содержимое:
Как видите, данный код почти на 100% аналогичен. Давайте посмотрим, что мы тут изменили.
- В 7 и 13 строке мы измении тип компонента с Rigidbody2d на Rigidbody, ведь мы уже имеем дело не с 2д, а с 3д.
- В 9 строке тип переменной moveVector изменён с Vector2 на Vector3, так как у игр 3D, три мировые оси а не две.
- В 19 строке мы изменили moveVector.y на moveVector.z, поскольку в 3D играх, ось по Y отвечает за верх. А вверх идти нельзя. Вверх можно передвигаться только с помощью прыжка, который мы реализуем в следующей статье.
На этом всё. Надеюсь данная статья научила Вас реализации передвижения персонажа, а так же показала в чём принципиальная разница передвижений между 2D и 3D играми.
Как сделать управление персонажем на Unity 3D и 2D. Уроки Unity для детей
Мы покажем, как запрограммировать движение персонажа в 2D- и 3D-проектах на Unity. Урок будет полезен детям и подросткам, которые начинают изучать Unity.
Разрабатывать игры на движке Unity (Юнити) могут дети уже с 10 лет. Создание игр является очень увлекательным, но трудоемким процессом, который требует много внимания и навыков. Чтобы сделать одну игру, нужно учесть много деталей, в том числе научиться делать управление персонажем на Unity. Школа программирования для детей «Пиксель» подготовила подробный урок о том, как научить персонажа двигаться в 2D- и 3D-играх на Unity. Вы также можете посмотреть видеоинструкцию (в конце статьи).
Начнем урок по Unity с разделения игровой сцены на два компонента, где первый — это площадка, по которой персонаж будет перемещаться. Иначе говоря, это Plane. Второй компонент — объект самого героя, Sphere.
Далее переходим к оживлению объектов. Управление персонажем на Юнити должно быть физически правильным. Обеспечить это позволяет компонент RigidBody. В инспекторе нажимаем Add Component, затем Physics и RigidBody.
Как заставить объекты существовать по своим законам? Именно вы являетесь создателем своего мира и вольны сами задавать ему физику. Проработка этого момента почти полностью лежит на скрипте. Писать его будем с помощью такого языка программирования, как Си Шарп (C#).
Создаем пустой скрипт и прописываем переменные, которые будут отвечать за скорость движения, быстроту поворота, передвижение по вертикали и горизонтали. В нашем случае переменные в Си Шарп будут названы MovementSpeed, TurningSpeed, vertical и horizontal соответственно.
В функции Update прописываем поворот персонажа по оси Y и движение по оси Z.
Остается только сохранить и скомпилировать созданную программу.
При работе в 2D-плоскости обучение на Unity становится немного проще, физика такого мира учитывает меньше физических параметров. Для начала добавим два спрайта, которые отвечают за персонажа и за поверхность, по которой он будет ходить. Наши спрайты вы можете скачать по ссылке.
Основы создания 2D персонажа в Unity 3D 4.3. Часть 2: бегущий персонаж
Всем привет. Продолжаем дело, начатое в первой части. Сейчас у нас есть платформа и стоящий на ней персонаж с анимацией покоя. Настало время научить нашего персонажа бегать вправо-влево по платформе.
Загрузим сцену из первой части. Напомню, что в прошлый раз мы импортировали несколько спрайтов в папку Assets — Sprites. На всякий случай, внизу поста еще раз приведу ссылку на спрайты. Среди них должен быть спрайт под названием Run. Мы будем использовать его для создания анимации бега. Для этого нам надо проделать те же действия по превращению одиночного спрайта в коллекцию, как и при создании анимации покоя. Вкратце напомню: выделяем спрайт, в окне Inspector устанавливаем свойство Sprite Mode как Multiple, нажимаем ниже Sprite Editor, нарезаем изображение в режиме Grid или Automatic.

Теперь в окне Hierarchy выбираем Character и переходим в окно Animation. Нажимаем на поле с анимацией Idle и выбираем Create New Clip, чтобы создать анимацию бега. Сохраним файл анимации в папке Assets — Animations под именем Run.

Новая созданная анимация Run стала текущей в окне Animation. Разворачиваем спрайт Run в окне Project, выделяем все фалы Run_0… Run_9 и перетаскиваем в окно Animation. Установим пока значение Sample равное 24.

Все это мы уже делали в первой части, а теперь будет нечто новое. Перейдем в окно Animator. Сейчас там отображены три анимации: Any State, Idle и Run. Нам предстоит задать условия перехода из анимации Idle в анимацию Run, то есть из состояния покоя в состояние бега. В нижнем левом углу есть поле Parameters. Нажимаем на плюсик, выбираем Float и называем новый параметр как Speed. Тем самым мы создали параметр типа число с плавающей запятой, обозначающий скорость перемещения персонажа. Именно в зависимости от значения этого параметра будет происходить переключение из анимации покоя в анимацию бега. Теперь нажимаем правой кнопкой мыши на анимацию Idle, выбираем Make Transition и нажимаем левой кнопкой мыши на анимацию Run. Между анимациями появится линия со стрелкой. Передвиньте мышкой прямоугольники анимации, если плохо видно. Кликнем по линии со стрелкой. В окне Inspector отобразятся свойства перехода между анимациями. Обратим внимание на низ окна, в раздел Conditions. Кликнем на параметр Exit Time и поменяем его на Speed. Второе поле Greater оставим без изменений, а в третьем введем значение 0.01. Мы создали условие перехода из анимации покоя в анимацию бега — оно происходит, когда значение параметра скорости становится немногим больше нуля.

Теперь нужно сделать обратный переход — из Run в Idle. Делаем все с точностью наоборот: Make Transition от Run к Idle, выделяем переход, в Conditions устанавливаем Speed — Less — 0.01.

Теперь у нас есть две анимации и условия перехода между ними. Но пока ничего работать не будет, потому что все что мы сделали нужно «оживить» при помощи скрипта. Давайте перейдем в окно Project и создадим в папке Assets подпапку Scripts. Добавим в нее новый C# Script, назовем его CharacterControllerScript и откроем на редактирование.

Я приведу полный листинг скрипта с подробными комментариями, а ниже еще поясню, что в нем происходит.
Итак, мы завели несколько переменных: для задания максимальной скорости перемещения, для определения направления (вправо/влево) и для работы с компонентом Animator. Почти все действия происходят в методе FixedUpdate. В нем мы получаем значение оси Х, которое меняется при нажатии на клавиатуре клавиш влево-вправо или A-D (если не меняли соответствующие настройки проекта!). Затем устанавливаем это значение параметру Speed компонента Animator. Обратите внимание, что мы берем модуль этого значения при помощи метода Mathf.Abs, так как при создании условий перехода между анимациями покоя и бега мы сравниваем значение параметра с положительным числом 0.01. Нам здесь не важно, в какую сторону бежит персонаж. Важно лишь величина значения. Далее задаем скорость перемещения по оси Х в соответствии со значением максимальной скорости. И, наконец, проверяем, в какую сторону бежит персонаж, и в какую сторону он в этот момент повернут. Если он бежит вправо, а повернут влево — разворачиваем его вправо путем инвертирования его размера по оси Х. И наоборот. Этим нехитрым способом мы избавились от необходимости делать две анимации вместо одной: для бега вправо и для бега влево.
Сохраняем скрипт. В Unity перетаскиваем его на нашего Character в окне Hierarchy. Запускаем игру, нажимаем влево-вправо или A-D.

Капитан Коготь теперь умеет бегать! Скорость анимации получилась быстроватой. Ее можно снизить путем уменьшения значения Sample в окне Animation для анимации Run (значение 12 будет нормально). Если одновременно с игрой у вас видно окно Animator, то вы увидите, что во время покоя работает анимация Idle (бегает синий прогрессбар), а во время бега происходит переход на анимацию Run, и, соответственно, работает она.
На этом пока все. Нам осталось разобраться с прыжками… и узнать при этом еще несколько новых вещей!
Ссылка на спрайты.
Система управления в 2D платформерах
Создание системы управления в unity , да и в играх в целом, очень специфичная область программирования. Ведь система подстраивается под нужды проекта, а значит и сложность ее будет зависеть от сложности проекта и уровня ваших знаний и подготовки.
Конечно, когда мы говорим о жанре платформер, тем более в 2D играх, то система управления здесь реализуется на порядок проще, чем в более крупных 3D играх, к тому же, Unity предлагает множество уже готовых решений и все, что вам требуется – только правильно их использовать.
Если на ПК управление в большей части реализуется за счет мыши и клавиатуры, то с сенсорными экранами все немножко сложнее. На экране не расположишь все кнопки, поэтому приходится прибегать к дополнительным системам отлавливания действий игрока и управления персонажем.
В этой статье попробуем рассмотреть один из примеров такой системы управления.
И так, начнем с небольшой программной части, а именно – с событийной части взаимодействия игрока и персонажа через команды.
Система команд
Так как игра предположительно будет работать на смартфонах, то кнопки управления персонажем будут находится на экране. Для создания пользовательского интерфейса используем систему Unity UI , поэтому создаем новый канвас на сцене, и три изображения кнопок управления: бежать влево Left run , вправо Right run и прыжок Jump .

Заметьте, что в примере используются не кнопки Button , а простые Image – дальше мы добавим весь необходимый функционал этим изображениям, чтобы они работали как кнопки.
Все команды по управлению персонажем будут поступать с панели UI . Чтобы разделять команды, заведем небольшое перечисление enum , где укажем, какие действия может принимать персонаж.
Создаем скрипт с перечислениями ActionType в котором будут находится команды.
- public enum ActionType <
- None = 0 ,
- MoveRight = 1 ,
- MoveLeft = 2 ,
- Jump = 3 ,
- Die = 4 ,
- >
Теперь создадим сам скрипт персонажа Character .
- public sealed class Character : MonoBehaviour <
- >
Добавим в этот скрипт метод, через который будут поступать команды персонажу.
- public sealed class Character : MonoBehaviour <
- public void OnDoAction ( ActionType action ) <
- print ( “Выполнить действие: “ + action );
- >
- >
Метод OnDoAction будет принимать определенною команду из перечисления ActionType .
Дальше создадим персонажа на сцене.
Мы используем бесплатный набор для персонажа и других объектов отсюда .
Дальше кидаем скрипт Character на персонажа на сцене и возвращаемся к канвасу, где продолжим настраивать наши кнопки.
Так как мы не используем стандартные кнопки Button по причине того, что они могут отловить только событие нажатия, мы будем настраивать изображения через компонент EventTrigger, который позволяет отлавливать кучу других полезных действий.
Чтобы добавить на изображение компонент EventTrigger , необходимо выбрать Image , перейти по вкладке Component -> Event и добавить компонент EventTrigger , ну или его можно найти по названию.

Этот компонент EventTrigger имеет все необходимые действия для работы с изображениями. Нам понадобится только PointerUp и PointerDown , для событий нажатия на изображение и события “отжатия”.
Поэтому нажимаем кнопку AddNewEventType в компоненте EventTrigger и ищем эти события, после чего добавляем их.

Почему именно PointerUp и PointerDown ?
Потому что персонаж будет передвигаться только пока вы “ зажали ” кнопку передвижения, после ее отпускания необходимо будет вызвать команду остановки, чтобы персонаж остановился.
Поэтому кнопкам Left run и Right run (влево и вправо), в компоненте EventTrigger добавим по одному действию к каждый список: в Pointer Down действие “ начала движения ”, а в Pointer Up действие “остановки движения” . Через эти действия мы будем передавать команды персонажу в метод OnDoAction .
Передавать команды в виде их названий через кнопки нельзя, поэтому возвращаемся в скрипт Character и создадим еще один, похожий на OnDoAction метод, в который будем передавать числовой номер команды actionId .
- public sealed class Character : MonoBehaviour <
- public void OnDoAction ( int actionId ) <
- OnDoAction (( ActionType ) actionId );
- >
- public void OnDoAction ( ActionType action ) <
- print ( “Выполнить действие: “ + action );
- >
- >
Теперь можно добавить действия кнопкам. В каждой кнопке, в списках Pointer Down и Pointer Up в качестве цели выбираем скрипт нашего персонажа Character , после чего, в раскрывающемся списке ищем метод OnDoAction .

Добавляем его в список действий.
Дальше в этих действиях указываем числовой номер команды из перечисления ActionType . К примеру, кнопка Right run в списке Pointer Down будет содержать метод OnDoAction с номером команды 1 – то есть, что в перечислении обозначает команду MoveRight , а в списке Pointer Up будет содержать тот же метод OnDoAction с номером команды 0, что обозначает исходное положение None из того-же перечисления. Кнопка Left run , в списке Pointer Down будет иметь номер команды 2 – MoveLeft .

С кнопкой Jump все еще проще, ей нужно добавить только одно событие Pointer Click , так как кнопка будет срабатывать один раз. Также добавляем в список действие и числовой номер команды – 3 Jump для прыжка.
После этого можно запустить и протестировать вызов команд в игре, нажатием на разные кнопки.

Обработка команд
Теперь, когда мы закончили с визуальной частью управления, переходим к самой обработке поступивших команд.
Возвращаемся в скрипт Character, где для начала добавим несколько переменных: переменную направления directionRight, и переключатели onMoving и onMakeJump для движения и совершения прыжка.
- public sealed class Character : MonoBehaviour <
- private bool directionRight = true ;
- private bool onMoving, onMakeJump ;
- public void OnDoAction ( int actionId ) <
- OnDoAction (( ActionType ) actionId );
- >
- public void OnDoAction ( ActionType action ) <
- print ( “Выполнить действие: “ + action );
- >
- >
Переменная directionRight будет указывать, что объект движется вправо когда ее значение будет true и влево, когда значение станет false , по умолчанию наш персонаж на сцене смотрит вправо, значит и переменная directionRight также будет иметь, по умолчанию, значение true . Другая переменная onMoving будет указывать на то что поступила команда двигаться с панели управления, то же самое и для переменной onMakeJump, только для команды прыжка.
Теперь переходим к методу OnDoAction, где разберем действия персонажа на поступившие команды.
Для начала разберем команды бега MoveRight и MoveLeft .
- public sealed class Character : MonoBehaviour <
- /*Остальной код…*/
- public void OnDoAction ( ActionType action ) <
- if ( action == ActionType . MoveRight ) <
- this . onMoving = this . directionRight = true ;
- > else if ( action == ActionType . MoveLeft ) <
- this . directionRight = false ;
- this . onMoving = true ;
- >
- >
- >
Используем простые условия: если поступила команда двигаться вправо MoveRight , то переменная directionRight становится true . Это значит, что персонаж будет двигаться вправо, то же самое делаем и для команды двигаться влево MoveLeft , только тогда значение directionRight будет false .
При поступлении команды None мы должны будем остановить любое движение персонажа – то есть перевести значение переменной onMoving в false .
- public sealed class Character : MonoBehaviour <
- /*Остальной код…*/
- public void OnDoAction ( ActionType action ) <
- if ( action == ActionType . MoveRight ) <
- this . onMoving = this . directionRight = true ;
- > else if ( action == ActionType . MoveLeft ) <
- this . directionRight = false ;
- this . onMoving = true ;
- > else if ( action == ActionType . None ) <
- this . onMoving = false ;
- >
- >
- >
Далее переходим к команде прыжка Jump .
Перед тем как выполнить эту команду, необходимо дополнительно проверить, стоит ли на “ земле ” наш персонаж. Для этого добавим простой коллайдер BoxCollider2D персонажу и настроим его.

В скрипте Character создадим новый метод CheckGround для проверки нахождения поверхности и переменную коллайдера objCollider .
- public sealed class Character : MonoBehaviour <
- /*Остальной код…*/
- private BoxCollider2D objCollider ;
- private bool CheckGround () <>
- public new BoxCollider2D collider <
- get <
- if ( this . objCollider == null ) this . objCollider = GetComponent < BoxCollider2D >();
- return this . objCollider ;
- >
- >
- >
Так как в игре персонаж будет иметь самый простой тип коллайдера – BoxCollider2D , то свойство collider будет возвращать именно этот компонент.
В методе CheckGround будем проверять, находится ли персонаж на поверхности. Для этого проверим коллайдер персонажа на соприкосновение с землей.
- private bool CheckGround () <
- Bounds bounds = this . collider . bounds ;
- Vector2 point = bounds . center ;
- Vector2 size = bounds . size ;
- bool result = Physics2D . OverlapBox ( point, size, 0f );
- return result ;
- >
Для этого используем позицию point и размер size коллайдера персонажа.
Далее методом Physics2D.OverlapBox проверим наличие поверхности под “ ногами ”.
Продолжаем работать с командой Jump, для этого вернемся в метод OnDoAction , где добавим новое условие.
- public sealed class Character : MonoBehaviour <
- /*Остальной код…*/
- public void OnDoAction ( ActionType action ) <
- if ( action == ActionType . MoveRight ) <
- this . onMoving = this . directionRight = true ;
- > else if ( action == ActionType . MoveLeft ) <
- this . directionRight = false ;
- this . onMoving = true ;
- > else if ( action == ActionType . None ) <
- this . onMoving = false ;
- > else if ( action == ActionType . Jump ) <
- if ( CheckGround ()) this . onMakeJump = true ;
- >
- >
- >
Проверим с помощью метода CheckGround поверхность и установим переменной onMakeJump значение true , чтобы совершить прыжок.
Вот так наш персонаж будет обрабатывать поступающие команды от игрока, теперь можно переходить ко второй части статьи – к методам передвижения персонажа.
Методы передвижения. Физика .
Для того, чтобы четко определить какую систему для перемещения объекта выбрать, Transform или Rigidbody , нужно решить? какими свойства этот объект будет обладать, ведь если он просто падает сверху вниз, это еще не повод сразу же использовать Rigidbody .
Физический движок Unity – это самостоятельная система обработки физических объектов и чем больше этих объектов будет на сцене? тем больше ресурсов уйдет на их обработку, так что для лучшей работы игры следует максимально минимизировать их кол-во.
Для персонажа выделим его главные требования: он должен четко взаимодействовать с окружением, которое состоит из коллайдеров, в первую очередь это пол и стены.
Для любого физического взаимодействия между объектами в Unity , эти объекты должны иметь компонент Rigidbody, ну или по крайней мере тот, кто совершает действие – в нашем случае это персонаж.
Самое главное, с чего нужно начать, так это выбрать методы обработки перемещения персонажа.
Если вы уже знакомы с компонентом Rigidbody , то значит замечали, что этот компонент похож на стандартный Transform . Оба этих компонента могут работать с позицией и поворотом персонажа, оба этих компонента можно использовать для перемещения объекта. Transform чаще используют для перемещения не физических объектов, например, для полета в игре огненного шара используется простое перемещение через Transform , но для физического объекта такое движение использовать не рекомендуется.
Методы обработки
Для обработки движения двух разных типов объектов ( Transform и Rigidbody ) существует два разных метода Update и FixedUpdate – каждый из них используется для своих целей.
Общее у этих методов то, что они оба вызываются через определенное время, Update – каждый кадр, а FixedUpdate – каждый промежуток времени.
В первом случае метод Update вызывается столько раз, сколько позволяет частота кадров в игре, то есть если у вас частота к примеру 60 кадров в 1 секунду, значит, что и метод Update сработает 60 раз за 1 секунду.
Метод Update отлично подходит для обработки движений с помощью Transform’а , так как движения, в этом случае, будут синхронизированы с обработкой графической составляющей игры, то есть все вычисления по перемещению будут выполнены в момент отрисовки кадра, отсюда следует, что объект будет занимать фактически именно ту позицию, которую вы видите на экране в данный момент.
Во втором случае имеем метод FixedUpdate . Этот метод выполняется через каждый промежуток времени, по умолчанию стоит значение – раз в 0.02 секунды, то есть вызов метода FixedUpdate происходит интервалом в 0.02 секунды. Физический движок работает отдельно от системы графической обработки в Unity и он не обязательно выполняет обработку физики каждый кадр, как это делает метод Update для движения Transform’а . При низкой частоте кадров (к примеру 1 кадр в 1 секунду) в игре могут возникать рывки и дерганья объектов Rigidbody во время перемещения. Поскольку расчет физики будет так же производится каждые 0.02 секунды – графическая система просто не будет успевать обновлять кадры с движением объекта, но при нормальной частоте кадров можно получить плавное и четкое взаимодействие всех физических объектов на сцене.
Главное различие между этими двумя методами, которое нужно запомнить это то, что FixedUpdate выполняет расчет физических параметров объекта, а Update, в первую очередь – графических .
Многие начинающие разработчики часто работают с Rigidbody в разных методах: ускоряют, замедляют их, придают им импульсы, бросают и так далее. Но с физическими телами рекомендуется работать именно в методе FixedUpdat. Даже если вы 10 раз измените позицию тела Rigidbody в том же методе Update или в любом другом методе, то все равно эти изменения вступят в силу только в момент вызова метода FixedUpdate, какая частота кадров у вас бы ни была.
Поэтому в примере работа с Transform’ом происходит только в методе Update , а с Rigidbody только в методе FixedUpdate .
В отличие от Transform’а у физического тела Rigidbody есть несколько способов перемещения.
- AddForce . Этот метод используется для придания импульса физическому объекту методом толчка. Для постоянного перемещения этот метод плохо подходит, так как им лучше пользоваться единожды, к примеру – для броска объекта или прыжка.
- MovePosition . Этот метод аналогичен методу SetPositionAndRotation компонента Transform , который просто перемещает физический объект в указанную позицию. Метод отлично подходит для равномерного движения, которое не предусматривает использования какого либо ускорения в режиме Kinematic. Для перемещения персонажа этот метод тоже не подходит, так как не позволяет использовать естественную силу притяжения на объекте.
- Velocity . Это свойство физического тела, которое показывает величину ускорения объекта. Свойство отлично подходит для задач, когда нужно замедлить или ускорить объект без резких толчков. Именно это свойство мы будем использовать для перемещения персонажа, так как оно позволяет управлять движением тела учитывая окружающее воздействие – гравитацию или преграды.
Движение с ускорением
Теперь попробуем применить выбранный тип движения для персонажа, для этого вернемся в скрипт персонажа Character, где создадим новый метод FixedUpdate и пару переменных для перемещения: moveSpeed для скорости движения и jumpForce для силы прыжка.
- public sealed class Character : MonoBehaviour <
- /*Остальной код…*/
- [ Range ( 0 , 10 )]
- public float moveSpeed = 5 ;
- [ Range ( 0 , 20 )]
- public float jumpForce = 10 ;
- private Rigidbody2D objBody ;
- private void FixedUpdate () <>
- public Rigidbody2D body <
- get <
- if ( this . objBody == null ) this . objBody = GetComponent < Rigidbody2D >();
- return this . objBody ;
- >
- >
- /*Остальной код…*/
- >
Перед движением сначала проверим, поступила ли команда движения персонажу с помощью переменной onMoving .
- public sealed class Character : MonoBehaviour <
- /*Остальной код…*/
- private void FixedUpdate () <
- if ( this . onMoving ) <
- >
- >
- /*Остальной код…*/
- >
Так как свойство ускорения тела velocity – это двумерный вектор Vector2 , то нам нужно будет указывать ускорение по двум осям – X и Y соответственно.
Сначала определим, в какую сторону персонажу нужно совершать ускорение по оси X. Для этого с помощью переменной directionRight проверим направление персонажа, если ее значение true, значит ускорять объект нужно вправо с положительным значением, если же значение false, то будем ускорять объект влево с отрицательным значением.
- public sealed class Character : MonoBehaviour <
- /*Остальной код…*/
- private void FixedUpdate () <
- if ( this . onMoving ) <
- float xVelocity, yVelocity ;
- if ( this . directionRight ) xVelocity = 1f ;
- else xVelocity = – 1f ;
- >
- >
- /*Остальной код…*/
- >
Теперь укажем скорость движения персонажа, используя переменную moveSpeed умноженную на дельту Time.fixedDeltaTime, чтобы учитывать время задержки между вызовами метода FixedUpdate .
- public sealed class Character : MonoBehaviour <
- /*Остальной код…*/
- private void FixedUpdate () <
- if ( this . onMoving ) <
- float xVelocity, yVelocity ;
- if ( this . directionRight ) xVelocity = 1f ;
- else xVelocity = – 1f ;
- float speed = this . moveSpeed * Time . fixedDeltaTime * 100f ;
- >
- >
- /*Остальной код…*/
- >
И в конце, умножим полученную скорость движения на ускорение xVelocity .
- public sealed class Character : MonoBehaviour <
- /*Остальной код…*/
- private void FixedUpdate () <
- if ( this . onMoving ) <
- float xVelocity, yVelocity ;
- if ( this . directionRight ) xVelocity = 1f ;
- else xVelocity = – 1f ;
- float speed = this . moveSpeed * Time . fixedDeltaTime * 100f ;
- xVelocity = xVelocity * speed ;
- >
- >
- /*Остальной код…*/
- >
Готово, у нас теперь есть скорость и направление движения персонажа по оси X , осталось добавить движение по оси Y, чтобы полностью составить вектор ускорения персонажа.
- public sealed class Character : MonoBehaviour <
- /*Остальной код…*/
- private void FixedUpdate () <
- if ( this . onMoving ) <
- float xVelocity, yVelocity ;
- if ( this . directionRight ) xVelocity = 1f ;
- else xVelocity = – 1f ;
- float speed = this . moveSpeed * Time . fixedDeltaTime * 100f ;
- xVelocity = xVelocity * speed ;
- yVelocity = this . body . velocity . y ;
- >
- >
- /*Остальной код…*/
- >
Здесь ускорение по оси Y оставляем неизменным – персонаж сам будет обрабатывает вертикальное ускорение.
Осталось только применить полученный вектор ускорения телу Rigidbody .
- public sealed class Character : MonoBehaviour <
- /*Остальной код…*/
- private void FixedUpdate () <
- if ( this . onMoving ) <
- float xVelocity, yVelocity ;
- if ( this . directionRight ) xVelocity = 1f ;
- else xVelocity = – 1f ;
- float speed = this . moveSpeed * Time . fixedDeltaTime * 100f ;
- xVelocity = xVelocity * speed ;
- yVelocity = this . body . velocity . y ;
- this . body . velocity = new Vector2 ( xVelocity, yVelocity );
- >
- >
- /*Остальной код…*/
- >
После проделанных действий наш персонаж сможет двигаться по горизонтали учитывая силу притяжения.
Чтобы проверить, добавим на сцену поверхность с коллайдером.
Теперь попробуем запустить игру и убедиться, что движение работает согласно командам.
Так, сейчас персонаж скользит по поверхности будто бы на льду, чтобы это исправить, как вариант, можно добавить физический материал коллайдеру поверхности и увеличить его коэффициент трения Friction .

Перекинем физический материал в поле Material коллайдера поверхности и снова тестируем.
Изменяя коэффициент трения Friction физического материала можно добиться нужно результата движения по поверхности.
Импульс
Теперь займемся прыжком персонажа. Как было сказано выше, для совершения прыжка физическим телом, будем использовать метод AddForce который придаст объекту импульс движения по вертикали.
Возвращаемся в метод FixedUpdate скрипта Character .
Импульс, как и ускорение, задается двумерным вектором Vector2 , но в отличие от ускорения, импульсу, помимо направления, еще необходимо передавать силу толчка.
Итак, получив команду прыжка Jump в методе FixedUpdate , после выполнения движения будем проверять переменную onMakeJump для совершения прыжка.
- public sealed class Character : MonoBehaviour <
- /*Остальной код…*/
- private void FixedUpdate () <
- if ( this . onMoving ) <
- float xVelocity, yVelocity ;
- if ( this . directionRight ) xVelocity = 1f ;
- else xVelocity = – 1f ;
- float speed = this . moveSpeed * Time . fixedDeltaTime * 100f ;
- xVelocity = xVelocity * speed ;
- yVelocity = this . body . velocity . y ;
- this . body . velocity = new Vector2 ( xVelocity, yVelocity );
- >
- if ( this . onMakeJump ) <
- print ( “Прыжок” );
- >
- >
- /*Остальной код…*/
- >
Здесь, как и при движении, также будем использовать две переменные для работы с направлениями, только теперь мы будем изменять направление по оси Y придавая ей силу прыжка с помощью переменной jumpForce , а по оси X объект будет двигаться согласно своему ускорению движения.
- public sealed class Character : MonoBehaviour <
- /*Остальной код…*/
- [ Range ( 0 , 20 )]
- public float jumpForce = 10 ;
- private void FixedUpdate () <
- if ( this . onMoving ) <
- float xVelocity, yVelocity ;
- if ( this . directionRight ) xVelocity = 1f ;
- else xVelocity = – 1f ;
- float speed = this . moveSpeed * Time . fixedDeltaTime * 100f ;
- xVelocity = xVelocity * speed ;
- yVelocity = this . body . velocity . y ;
- this . body . velocity = new Vector2 ( xVelocity, yVelocity );
- >
- if ( this . onMakeJump ) <
- float xVelocity = this . body . velocity . x ;
- float yVelocity = this . jumpForce ;
- >
- >
- /*Остальной код…*/
- >
Далее передаем телу Rigidbody импульс через метод AddForce .
- public sealed class Character : MonoBehaviour <
- /*Остальной код…*/
- private void FixedUpdate () <
- if ( this . onMoving ) <
- float xVelocity, yVelocity ;
- if ( this . directionRight ) xVelocity = 1f ;
- else xVelocity = – 1f ;
- float speed = this . moveSpeed * Time . fixedDeltaTime * 100f ;
- xVelocity = xVelocity * speed ;
- yVelocity = this . body . velocity . y ;
- this . body . velocity = new Vector2 ( xVelocity, yVelocity );
- >
- if ( this . onMakeJump ) <
- float xVelocity = this . body . velocity . x ;
- float yVelocity = this . jumpForce ;
- Vector2 force = new Vector2 ( xVelocity, yVelocity );
- this . body . AddForce ( force, ForceMode2D . Impulse );
- this . onMakeJump = false ;
- >
- >
- /*Остальной код…*/
- >
Теперь снова вернем переменной onMakeJump исходное значение false для следующего прыжка. Наш персонаж может прыгать по поверхностям, попробуйте запустить и проверить результат.
Чтобы персонаж не прыгал так высоко и приземлялся быстрее можно в настройках физики Unity повысить силу гравитации. Эти настройки можно найти выбрав Edit -> Project settings -> Physics2D , в параметре Gravity увеличиваем Y составляющую.

Снова проверим результат.
Заключение
Вот так легко и просто можно создать систему управления персонажем с помощью команды игрока. Теперь вы запросто сможете подключить к готовому персонажу анимации и добавить в игру другие объекты.