Скрипт движения 2D персонажа
Еще один скрипт управления персонажем, заточенный под 2D физику. В отличии от прочих, здесь имеются некоторые настройки. Возможен выбор осей. Например, если выбрать только ось Х, в этом случаи включается режим как для платформера, персонаж может двигаться по горизонтали и использовать прыжок. Если выбрать оси ХY, тогда скрипт переходит в режим как для скроллера, проще говоря, подходит для управления неким самолетом или вроде того, объект может двигаться не только по горизонтали, но и по вертикали, а та-же самая клавиша, что и в первом варианте, на этот раз выполняет роль ускорителя, то есть добавляет скорости. Кроме того, есть опция отслеживания позиции курсора, чтобы персонаж смотрел на него.
Создаем новый C# скрипт Player2DControl, со следующим содержанием:
speed — скорость движения, как не странно.
addForce — если выбран режим Оnly X, будет использовано для прыжка, при нажатии соответствующий клавиши. Во втором режиме, значение addForce будет прибавлено к speed, тем самым придавая ускорение.
lookAtCursor — отслеживание позиции курсора, персонаж будет вращаться по оси Z. Важно помнить, что лицом считается ось Х.
isFacingRight — если на старте сцены персонаж смотрит вправо, то надо ставить true.
При движении только по горизонтали, разворот персонажа осуществляется через функцию Flip. Так же, чтобы прыжок был возможен, все объекты по которым возможно передвижение, как бы земля/поверхность, у всех них должен быть тег Ground.
Передвижение персонажа в 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 играми.
Система управления в 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 составляющую.

Снова проверим результат.
Заключение
Вот так легко и просто можно создать систему управления персонажем с помощью команды игрока. Теперь вы запросто сможете подключить к готовому персонажу анимации и добавить в игру другие объекты.
Full Unity 2D Game Tutorial 2019 – Player Movement
In this section of the tutorial we will create a player object that we can control with the keyboard or controller. We will then focus on Player Movement using the physics engine provided in unity.
Full Unity 2D Game Tutorial 2019 – Creating the player object
The first step is to right click in your Hierarchy view. This will bring up a menu where we can add all the things. We won’t though, we just need to create a single empty GameObject by clicking the Create Empty option. This will create a new item in the hierarchy. With the new object selected in the hierarchy view press F2 or right click rename to rename the object to PlayerObject. This will be the root element of our player. It will hold all the objects that make up our player such as sprites.
Now, lets add a sprite to our PlayerObject so we can see our player in both the Scene view and game view. To do that we select the PlayerObject and right click to get the context menu again and select 2D Object > Sprite.
We have added a Sprite to our player but we still can’t see anything. This is due to the default sprite not having any image associated with it. We will add that now. With the New Sprite object selected view the inspector window and click the nipple (yes that’s what its called, no giggling we’re a mature game developer). A new window pops up with all the Sprites you have by default in your project. Select the Knob(no giggling) by double clicking it or hitting the enter key with it selected.
Yay! we should now be able to see out player in the Scene view. Let’s rename the New Sprite to something that will help identify what this object is like PlayerSprite.

Full Unity 2D Game Tutorial 2019 – Coding our Player Movement
Our player doesn’t do much at the moment because we haven’t told it to do anything yet. In order to do that we must add some code. Since we want the code to affect the player and all it’s components we will add the code to the PlayerObject. With the PlayerObject selected go to the Inspector window and click the Add Component button. Here we can add all sorts of prebuild components but for now lets just add a Player script. Type Player in the search bar at the top to get selection of Video Player or New script. Select new script and click the Create and Add button to make the script for us.
We now have a script in our project called Player. Eventually we will have a lot of scripts and it will become hard to find things in the Project window so lets make things easier for our future selves by creating a folder and calling it Scripts. This will house all our future scripts and keep the Project view organized for us. Simply drag and drop the Player script into the Scripts folder and let’s continue.

Double clicking our Player script should open visual studio with the Player script already open in the code view window. When a script is first created you are given 2 methods; Start and Update. The Start method is called once when the object is created and Update is called once per frame after. This allows us to setup the player with values once in the start method and then update the player in the Update method from then on.

In the first part of our code add these two variables. These will be used to set our player speed and health.