Популярное
Свежее
Моя лента
Сообщения
Рейтинг
Пополнить Steam
Низкая комиссия
Темы
Игры
Офтоп
Гайды
Ночной музпостинг
Вопросы
Hollow Knight
Музыка
Творчество
Кино и сериалы
Арт
Показать все
DTF
О проекте
Правила
Реклама
Приложения
Аккаунт удален
05.11.2020

Статья удалена

1я часть

2я часть

Полные версии кода будут находиться в конце поста.

Начинаем добавлять анимации персонажа.

Повороты

Для начала добавим персонажу умение поворачиваться в нужную сторону при движении влево и вправо.

В PlayerBehaviour получаем доступ к нашему спрайту через spriteRenderer.

private SpriteRenderer spriteRenderer; private void Start() { rigidBody = gameObject.GetComponent<Rigidbody2D>(); coll = gameObject.GetComponent<Collider2D>(); spriteRenderer = gameObject.GetComponent<SpriteRenderer>(); }

Опция spriteRenderer.flipX по-умолчанию имеет значение false. Если задать ей значение true, то спрайт будет отзеркален по оси Х.

private void updatePlayerPosition() { float moveInput = Input.GetAxis("Horizontal"); float jumpInput = Input.GetAxis("Jump"); if (moveInput < 0) { // Влево rigidBody.velocity = new Vector2(-xVelocity, rigidBody.velocity.y); spriteRenderer.flipX = true; } else if (moveInput > 0) { // Вправо rigidBody.velocity = new Vector2(xVelocity, rigidBody.velocity.y); spriteRenderer.flipX = false; } else if (coll.IsTouchingLayers(ground)) { rigidBody.velocity = Vector2.zero; // Отключение инерции в стороны } if (jumpInput > 0 && coll.IsTouchingLayers(ground)) { rigidBody.velocity = new Vector2(rigidBody.velocity.x, yVelocity); } }

Тестируем

Состояние покоя (idle)

В папке Assets создаём папку Animations. В ней, создаём анимацию, которую мы назовем idle (персонаж находится в состоянии покоя).

Статья удалена

Перетаскиваем нашу анимацию на объект Player слева в иерархии.

Теперь мы можем увидеть, что в него добавился новый компонетнт Animator.

Статья удалена

Если перейти во вкладку Animator, то мы должны увидеть примерно следующее. Наш объект idle добавлен.

Статья удалена

Нужные нам спрайты лежат Assets/BayatGames/Free Platform Game Assets/Character/Character Animation ( Update 1.8 )/Idle/1x.png

Мы использовали этот спрайт-карту (так оно, вроде, называется) в первой части, где нарезали её и использовали для спрайта персонажа.

Перетаскиваем окно Animation так, чтобы было видно сцену и персонажа.

Тыкаем на нашего персонажа в иерархии, чтобы в Animation появилась наша анимация idle. Выделяем все спрайты при помощи шифта, и перетаскиваем в поле с временной шкалой.

Статья удалена

Немножко растянем спрайты по времени (синии ромбы над спрайтами), чтобы все выглядело получше - иначе анимация будет слишком быстрой, и незаметной.

Самый простой способ, выделить их при помощи шифта на временной шкале, и растянуть, потянув за синюю полосу, появившуюся справа.

Теперь персонаж "дышит". Не супер, но что поделать =)

Для того, чтобы увидеть это в игре, нужно ткнуть на нашу анимацию в ассетах, и жмакнуть чекбокс Loop Time в инспекторе.

Статья удалена

Бег (run)

Создаём новую анимацию под названием "run" в папке Animations, и перетаскивам её на объект Player в иерархии.

Переходим во вкладку Animator.

Статья удалена

Теперь создадим саму анимацию.

Находим нужные нам спрайты в Assets/BayatGames/Free Platform Game Assets/Character/Character Animation ( Update 1.8 )/Run/1x.png, и нарезаем их, как делали в первой части.

Статья удалена

Открываем вкладку Animation, выбираем объект Player в иерархии.

Во вкладке Animation тыкаем run и переносим наши нарезаные спрайты на временную шкалу, где равномерно их "размазываем".

Статья удалена

Наблюдаем за результатом.

Отлично. Теперь добавим анимацию в саму игру.

Для начала настроим переходы между анимациями в Animator.

Тыкаем на idle, и создаем переход (Make Transition), который протягиваем в run, затем делаем то же самое, но наоборот.

В итоге мы должны иметь 2 перехода idle => run и run => idle.

Статья удалена

Для каждого из переходов проставляем опции, которые помогут не завершать анимацию по времени, а только по заданным условиям.

Статья удалена

Создадим параметры для того, чтобы переключатсья между состояниями персонажа.

В частности, содадим int (целое число) параметр под именем state.

Статья удалена

Пусть значение 1 будет бегом, значение 0 будет стоянием на месте (позже добавим сюда прыжки).

Задаём условия для переходов, как на картинке ниже:

idle => run , если state === 1

run => idle, если state === 0

Статья удалена

Переключаем наш state, и наблюдаем за результатом.

Обновляем код в самом начале скрипта PlayerBehaviour. Нам нужен доступ к аниматору.

private Rigidbody2D rigidBody; private Collider2D coll; private SpriteRenderer spriteRenderer; private Animator animatorComponent; private void Start() { rigidBody = gameObject.GetComponent<Rigidbody2D>(); coll = gameObject.GetComponent<Collider2D>(); spriteRenderer = gameObject.GetComponent<SpriteRenderer>(); animatorComponent = gameObject.GetComponent<Animator>(); }

Благодаря этому, мы можем изменять наше значение state в методе updatePlayerPosition.

private void updatePlayerPosition() { float moveInput = Input.GetAxis("Horizontal"); float jumpInput = Input.GetAxis("Jump"); if (moveInput < 0) { // Влево rigidBody.velocity = new Vector2(-xVelocity, rigidBody.velocity.y); animatorComponent.SetInteger("state", 1); // Бег spriteRenderer.flipX = true; } else if (moveInput > 0) { // Вправо rigidBody.velocity = new Vector2(xVelocity, rigidBody.velocity.y); animatorComponent.SetInteger("state", 1); // Бег spriteRenderer.flipX = false; } else if (coll.IsTouchingLayers(ground)) { rigidBody.velocity = Vector2.zero; // Отключение инерции в стороны animatorComponent.SetInteger("state", 0); // Стоим } if (jumpInput > 0 && coll.IsTouchingLayers(ground)) { rigidBody.velocity = new Vector2(rigidBody.velocity.x, yVelocity); } }

Тестируем, что у нас получилось.

Вполне не плохо. Осталось анимировать прыжок и падение + добавить функцию-менеджер нашего state.

Полный код

PlayerBehaviour

using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerBehaviour : MonoBehaviour { /** ** Ускорение игрока **/ [Header("Player velocity")] // Ось Ox public int xVelocity = 5; // Ось Oy public int yVelocity = 8; [SerializeField] private LayerMask ground; private Rigidbody2D rigidBody; private Collider2D coll; private SpriteRenderer spriteRenderer; private Animator animatorComponent; private void Start() { rigidBody = gameObject.GetComponent<Rigidbody2D>(); coll = gameObject.GetComponent<Collider2D>(); spriteRenderer = gameObject.GetComponent<SpriteRenderer>(); animatorComponent = gameObject.GetComponent<Animator>(); } private void Update() { updatePlayerPosition(); } // Обновляем местоположение игрока private void updatePlayerPosition() { float moveInput = Input.GetAxis("Horizontal"); float jumpInput = Input.GetAxis("Jump"); if (moveInput < 0) { // Влево rigidBody.velocity = new Vector2(-xVelocity, rigidBody.velocity.y); animatorComponent.SetInteger("state", 1); // Бег spriteRenderer.flipX = true; } else if (moveInput > 0) { // Вправо rigidBody.velocity = new Vector2(xVelocity, rigidBody.velocity.y); animatorComponent.SetInteger("state", 1); // Бег spriteRenderer.flipX = false; } else if (coll.IsTouchingLayers(ground)) { rigidBody.velocity = Vector2.zero; // Отключение инерции в стороны animatorComponent.SetInteger("state", 0); // Стоим } if (jumpInput > 0 && coll.IsTouchingLayers(ground)) { rigidBody.velocity = new Vector2(rigidBody.velocity.x, yVelocity); } } }

CameraBehaviour (в этой части не изменялся)

using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class CameraBehaviour : MonoBehaviour { // Добавляем объект, за которым будет двигаться камера [Header("GameObject")] // Пишу с нижним подчеркиванием, так gameObject - ключевое слово Unity. // а придумывать новое название переменной мне влом (сорян) public Transform _gameObject; [Header("Camera position restrictions")] public float minY; public float maxY; public float minX; public float maxX; void Update() { UpdateCameraPosition(); } // Изменяем позицию камеры на экране void UpdateCameraPosition() { try { transform.position = new Vector3( // Положение игрового объекта, за которым мы двигаемся Mathf.Clamp(_gameObject.position.x, minX, maxX), Mathf.Clamp(_gameObject.position.y, minY, maxY), // Положение камеры z должно оставать неизменным transform.position.z // (если камеры куда-то проваливается, заменить на, например, -10) ); } catch (Exception error) { // Ловим ошибку, если по каким то причинам код не может быть выполнен (например, забыли подставить объект в _gameObject) Debug.LogError(error); } } }

Скорее всего, нужно будет завести себе репу для всего этого дела, чтобы не выкладывать сюжа простыни кода. Займусь, если будет время ;)

#unity