юнити код для движения персонажа
Продолжаем делать наш Unity for dummies платформер.
Полные версии кода будут находиться в конце поста.
Если вы не в курсе, как работают хуки жизненного цикла в Unity, вы можете ознакомиться с данной статьёй.
Создаём в панели ассетов C# cкрипт PlayerBehaviour, и запихиваем его в папку Scripts (её можно создать в той же панели ассетов).
Затем выбираем наш объект Player слева, в меню иерархии, и закрепляем инспектор (меню справа), нажав на замок в верхнем правом углу.
Пока закрываем все ненужные компоненты (Box Collider 2D, etc), нажимая на стрелочку у каждого из них.
Теперь перетаскиваем наш скрипт в инспектор, и он прикрепляется к объекту Player (если вы не выполнили предыдщуий пункт с закрепением меню, то вы этого сделать не сможете).
Если зайти в Edit => Project Settings => Input Manager, то мы можём увидеть настройки управления. Например, прыжок (Jump) назначен на пробел, в то время, как движение по горизонтали назначено на a, d, ←,→.
Запомним это для того, чтобы затем использовать в коде (названия инпутов Jump, Horizontal).
Пора покодить. Два раза нажимаем на наш скрипт PlayerBehaviour, и Unity отдаст его в руки Visual Studio.
Сохраняем файл, и переходим обратно в Unity. После того, как Unity проверит код (линтинг, ошибки, пустые переменные). Если что то неправильно, то вы увидите сообщение об ошибке.
Исправляем код, и страшные красные буквы исчезают. Можно запустить игру, и проверить, как все работает.
Мне не нравится, что персонажа переворачивает. Исправим.
Заходим в инспектор, открываем Rigidbody2D и ставим галочку на Freeze Rotation Z.
Есть два основных способа научить камеру двигаться за персонажем.
1. Подвинуть камеру внутри сцены, чтобы она была на персонаже, а затем в привязать камеру к объекту персонажа через меню иерархии.
2. Задать движение камеры за персонажем програмно.
Создаём скрипт CameraBehaviour, и привязываем его к объекту Main Camera (добавляем через инспектор).
Открываем наш новый скрипт, и начинаем кодить (да, мне на работе не хватает, продолжаю и после).
Фиксируем объект камеры на замок в инспекторе, и перетаскиваем наш объект Player в GameObject.
Теперь камера двигается за игроком.
Однако камера постоянно вылезает за пределы уровня, показывая синий фон.
Я не уверен, что моё решение правильное. Буду рад, если кто-нибудь поделится своими соображениями на данный счёт.
Добавляем в наш скрипт CameraBehaviour следующий код:
Двигаем камеру, и снимаем наши измерения ее положений.
На скрине ниже камера стоит в левом нижнем углу сцены.
Проставляем снятые позиции для камеры (мои и ваши позиции будут отличаться).
Теперь обновим метод UpdateCameraPosition в скрипте CameraBehaviour
Отлично, камера перестала «гулять». Работаем дальше.
Выбираем наш Foreground, и создаём новый слой ‘Ground’ в инспекторе.
Снова тыкаем на Foreground, и выбираем в поле Layer наш только что созданный слой.
Добавим в PlayerBehaviour такую строчку.
Теперь в объекте Player мы можем выбрать наш свежесозданный слой.
Обновляем наш PlayerBehaviour. Добавим коллайдер (rigidBody мы создавали ранее).
Теперь мы можем обновить обработку перемещения персонажа в методе updatePlayerPosition
Летать мы разучились, а по платформе больше не скользим. Победа!
Я не уверен, что моё решение правильное. Буду рад, если кто-нибудь поделится своими соображениями на данный счёт
Привет.
Я, конечно, дохуя вовремя, когда у тебя уже пять статей и рефакторинг, но вот щас иду за тобой пока вот на этом месте.
Короче, в ассет-сторе есть проект 2D Game Kit от разрабов движка. Там движение камеры сделано буквально следующим образом, если помню (давно открывал). Уровень завёрнут в коллайдер, ещё один коллайдер на камере. Соответственно, когда она о него стукается, то расслабляется и не двигается. И ещё там угарный камера-лаг стоит, чтоб камера не жёстко следовала за персонажем, а как бы за верёвочку.
Привет.
Да, я изначально так и пробовал.
Но персонаж, почему-то, попросту исчезает при старте игры.
Попробую ради эксперимента новый проект создать.
Как заставить персонажа двигаться в Unity 2d
В прошлой статье мы рассказывали вам как создать анимацию в 2d проекте Unity5. В этой статье мы продолжим и реализуем движение нашей «птицы» — персонажа при помощи компонента rigidbody 2d «физики».
На нашей сцене уже имеется заготовка персонажа с анимацией, добавим к ней компоненты Box Collider 2d и Rigidbody 2d и настроим компонент так как на скриншоте
Далее создадим скрипт к примеру TransformPlayer с таким кодом:
В этом скрипте указано, что при нажатии на кнопку w значение гравитации у персонажа меняется, а при отпускании, клавиши значение восстанавливается, таким образом, персонажа всегда падать, если не нажимать кнопку w.
Далее, как токового движения вперед у нас не реализовано, но симуляцию движения можно реализовать при помощи фоновых объектов.
Добавим на сцену спрайты земли и продублируем 4 раза, на каждый компонент вешаем те же компоненты Box Collider 2d и Rigidbody 2d, создадим еще один скрипт TransformGround
Теперь подробнее… Создадим на камере два пустых объекта, один разместим слева и добавим Box Collider 2d и Rigidbody 2d, так же присвоим ему тэг, который указали в скрипте barer, а другой справа. Примерно так…
На объектах «земли» укажем этот объект который справа.
Теперь можно поверить запустив игру
Птица управляется, движение земли создает эффект движения птицы. В следующих уроках можно реализовать рандомное появление объектов на сцене и столкновение персонажа с ними. На это все удачных проектов.
Юнити код для движения персонажа
Нажимаем «Add component>>Physics>>Rigidbody» и «Add component>>Physics>>Capsule Collider». В «Capsule Collider» Выставляем размеры нашей капсулы что бы получилось как на картинке, слегка чуть больше модельки самой.
В «Rigidbody» ставим галочку «Use gravity». Раскрываем вкладку «Constraints» и ставим все 3 галочки на «Freeze Rotation». Это нужно для того что бы наш персонаж не проваливался сквозь землю, не падал на землю если вдруг окажется на неровности и тому подобное.
Программируем персонажа на перемещение.
Создадим c# скрипт «movePlayer».
200?’200px’:»+(this.scrollHeight+5)+’px’);»> using UnityEngine;
using System.Collections;
public class movePlayer : MonoBehaviour <
private GameObject player; //Переменна объекта персонажа с которым будем работать.
public static int speed = 6; //Скорость перемещения персонажа. Запись public static обозначает что мы сможем обращаться к этой переменной из любого скрипта
public static int _speed; //постоянная скорость перемещения персонажа
public int rotation = 250; //Скорость пповорота персонажа
public int jump = 3; //Высота прыжка
//Поворачиваем персонажа. Так как наша переменная x глобальна, из скрипта камеры в неё будем записывать длину на сколько сместился указатель мыши и по оси X и относительно этого будет повернут наш персонаж
Quaternion rotate = Quaternion.Euler (0,x,0); //Создаем новую переменную типа Quaternion для задавания угла поворота
player.transform.rotation = rotate; //Поворачиваем персонаж
200?’200px’:»+(this.scrollHeight+5)+’px’);»> codeusing UnityEngine;
using System.Collections;
private float x = 0.0f; //Угол поворота по Y?
private float y = 0.0f; //Уго поворота по X?
[AddComponentMenu(«Scripts/Mouse Orbit»)] //Добавляем в меню
public void Start() <
//переворачивам углы
Vector3 angles = transform.eulerAngles;
x = angles.y;
y = angles.x;
if(rigidbody)
rigidbody.freezeRotation = true; //Если камера столкнется с физ.объектомона остановиться
>
y = ClampAngle(y,yMinLimit, yMaxLimit); //Вызыв самописной функции для ограничения углов поврот
movePlayer.x = x;
//Повернуть камеру согласно поченым данным
Quaternion rotation = Quaternion.Euler(y, x, 0);
transform.rotation = rotation;
200?’200px’:»+(this.scrollHeight+5)+’px’);»> using UnityEngine;
using System.Collections;
public class AnimatePlayer : MonoBehaviour <
Основы создания 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, и, соответственно, работает она.
На этом пока все. Нам осталось разобраться с прыжками… и узнать при этом еще несколько новых вещей!
Ссылка на спрайты.
Правильная реализация передвижения персонажа
Почему один обьект проходит сквозь другой хотя у меня есть коллайдеры на обоих обьектах?
Почему мой персонаж во время движения проходит сквозь другой обьект, а потом его откидывает назад?
Как реализовать передвижение персонажа в Unity3d правильно?
Почему так часто используется передвижение через transform.position и почему это неправильно?
Почему мой персонаж движется с разной скоростью если проседает FPS?
Почему двигать персонажа через смену transform.position неправильно?
Как сделать прыжок от пола, но так что бы персонаж не мог бесконечно взлетать
Почему когда платформа движется, персонаж стоящий на платформе остается на месте?
Все эти вопросы, фактически, являются одним единым вопросом, который слишком уж часто встречается у начинающих.
Заодно создал тэг unity3d-faq
1 ответ 1
Перед прочтением важно знать
Хоть я здесь и разбираю в т.ч. нефизическое движение, я настоятельно рекомендую использовать ФИЗИЧЕСКОЕ движение. И переходить на нефизическое только в исключительных ситуациях.
Я буду использовать здесь 2 термина: «телепортация» и «плавное движение». В моем понимании:
Есть люди у которых мнение отличается.
Учтите, что все что написано ниже упирается в верхние значения терминов, а не эти.
Двигать обьекты в игровых движках можно следующими способами:
используя физический движок (движение обусловленное физической моделью игрового движка)
Движение реализуемое через CharacterController (здесь пока что не рассматривается т.к. новички в его сторону вообще не смотрят, может, позже распишу)
Новички очень часто использую телепортацию на каждом кадре, что есть критически неправильным подходом. Потом на SO появляются кучи клонов вопросов вроде «почему персонажа дергает возле стены?» или «почему он проходит сквозь стену?» или «почему пуля не всегда наносит урон?» и подобные.
Нужно запомнить всего одно правило: Двигать/поворачивать через присвоение transform.position / transform.rotation нельзя. Это порождает проблемы. В любом случае это вам вылезет боком.
Пример правильной реализации движения:
( на примере обьекта-шара )
в отличии от пестрящих дичью форумов, в т.ч. сервисе вопросов/ответов от юнити. Там в таких темах слишком часто пишут ответы те люди, которые понятия не имеют о правильном подходе.
Связанные с темой понятия:
Если обьект не обладает физическими свойствами (не имеет RigitBody) эти параметры и методы можно использовать для НЕфизического передвижения.
Например поворот камеры.
Или крутящийся куб на небосводе.
Мы не получим дергающуюся картинку при проседании кадров если сделаем НЕФИЗИЧЕСКОЕ движение правильно:
мы присваиваем в новую позицию:
Про физические свойства движения.
мы разово задаем вектор скачка. Только 1 долю секунды. Но он будет изменятся во времени автоматически равномерно уменьшаясь под силой тяжения. Пока не станет нулевым (верхняя точка прыжка), а потом не пойдет в минус по Y (падение), а потом не упадет на землю и не отскочит от нее (снова плюс по Y ) и так до полной остановки физической скорости обьекта на земле.
Если девайс с игрой сильно загружен, вызов методов Update() / FixedUpdate() тоже может просесть в скорости. И если в физике это учтено и без нас, то сейчас мы делаем НЕ физическое движение и именно по-этому это нужно учитывать добавлением даного множителя.
Но и без использования даного множителя у нас не появится проблем с провалами сквозь стены. Это просто фикс скорости.
Пример простой но хорошей НЕФИЗИЧЕСКОЙ реализации кода движения на примере персонажа.
Если в прошлом примере мы двигали шар, то было допустимо его толкать используя физ.модель. То есть мы использовали AddForce() для этих целей.
Давайте актуализируем этот код под даного персонажа. Мы заменим физический толчек обьекта на не-физическое, но ПЛАВНОЕ перемещение обьекта в пространстве:
С этим кодом мы получим такой результат:
С такой реализацией у нас не будет проблем вроде скачков скорости на проседании или повышении количества FPS, проваливаний, дерганости, прохождения сквозь стены или других неожиданностей.
Так же можно добавить анимацию бега на нашего персонажа (ну если бы это был не куб).
Но как же реализация на физике?
Да, можно подобное реализовать и на физике.
Наша прошлая версия скрипта имела несколько недостатков. А именно:
Давайте поместим на наш куб CapsuleCollider (минимальное торможение из-за силы трения) и заблочим в rigitBody rotateX и rotateZ (что б наш персонаж не падал на бок).
А потом нацепим на него вот этот скрипт:
Вы видите эту плавность, как будто человек бежит, останавливается, бежит в другую сторону? Красота!
А теперь вернитесь к прошлой гифке и присмотритесь. Движение совсем не такое 🙂 Там как буд-то рукой двигают шахматную фигуру по доске.
Ну и описанные выше баги поведения были пофикшены с такой реализацией.
Можно добавить еще физический материал нашему персонажу и откоректировать его поведение.
Вообще улучшать реализацию можно до бесконечности. Но, думаю, основные проблемы СПОСОБОВ ПЕРЕДВИЖЕНИЯ с которыми вы столкнетесь, я затронул 🙂
Оптимально использовать именно передвижение на базе физики.
Пытайтесь использовать исключительно физическое передвижение.
Реализация нестандартной физики движений.
Одним из моих любимейших примеров нестандартной физики движения является игра Ori and the Blind Forest
Такое перемещение/такие прыжки невозможно сделать на основе стандартной физики. Вероятнее всего, это делалось через физическое перемещение + костыли для получения нужных эфектов которые противоречат стандартной физике.
Сначала разрабатываются концепты движения. Они делаются в любом видеоредакторе с примитивными фигурами. Вот пример (если станет недоступным искать можно по Ori and the blind forest Enemy Concepts ) :
Обратите внимание на то, то здесь прорисовано не только перемещение обьекта, но и его вытягивания/сжатия. Изменения формы во время любого взаимодействия с внешним миром. В т.ч. выстрелы так же влияют на форму. А так же что указываются радиусы опознавания главного героя каждым отдельным врагом.
Костыли для каждого персонажа/врага свои собственные. Это делается что бы каждый из них обладал своей уникальной физикой. Сделать это на общей физике навряд ли возможно.
Движение реализовано «правильно» но предмет все равно пролетает сквозь стену
ДАЖЕ если вы реализовали физическое передвижение вашего персонажа, все равно может случится такое, что просчет CollisionDetect может проходить с ошибками. Такое бывает.
Для таких случаев есть настройки отвечающие за обработку CollisionDetect в настройках самого RigitBody.
Желательно такого не делать т.к. это негативно сказывается на производительности. Чем на большем количестве обьектов вы меняете эти настройки, тем более вероятно что вы делаете какую-то дичь, которую делать совсем не нужно. Считайте это спасательным кругом, а не панацеей. А если вы так будете делать, то рано или поздно вы прийдете на SO с вопросом почему игра тормозит, вас попросят показать код и ничего не найдут просто потому, что проблема тормозов не в коде. И намучаетесь вы с оптимизациями ой как сильно.