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

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

Предыдущие части:

  1. Создаём уровень при помощи Tilemap. Добавляем персонажа.
  2. Учим двигаться камеру и персонажа. Добавляем ограничения для движения камеры.
  3. Добавляем анимации бега и спокойного состоянии для персонажа.
  4. Пишем простой менеджер анимаций. Добавляем анимации прыжка и падения.

Рефакторим код и добавляем сбор предметов.

Рефакторим код и обновляем параметры

Так как изначально я писал всё это чисто для себя, я не слишком следил за именами переменных и прочим (к тому же, писал на C# второй раз в жизни).

После многочисленных... Комментария от неравнодушного Капитана (он, кстати, написал очень интересную статью Частицы по типу поверхности в Unity), я решил отрефакторить свой код, и, наконец, завести репу под это дело.

Код после рефакторинга доступен по ссылке.

Обновлены имена переменных и методов, в обоих файлах изменена логика работы с координатами.

PlayerBehaviour

В PlayerBehaviour ускорение игрока теперь задаётся через Vector2.

/** * Ускорение игрока по осям Ox и Oy **/ public Vector2 playerVelocity = new Vector2(5, 8);

Значения для местоположения игрока берутся из playerVelocity.x и playerVelocity.y соответственно.

private void UpdatePlayerPosition() { // Получаем значения для горизонтального движения или прыжка, если соответствующая кнопка нажата float horizontaMoveInput = Input.GetAxis("Horizontal"); float jumpInput = Input.GetAxis("Jump"); // Движение влево if (horizontaMoveInput < 0) { rigidBody2dComponent.velocity = new Vector2(-playerVelocity.x, rigidBody2dComponent.velocity.y); spriteRendererComponent.flipX = true; // Движение вправо } else if (horizontaMoveInput > 0) { rigidBody2dComponent.velocity = new Vector2(playerVelocity.x, rigidBody2dComponent.velocity.y); spriteRendererComponent.flipX = false; // Если персонаж стоит на земле и не двигается, отключаем инерцию } else if (collider2dComponent.IsTouchingLayers(ground)) { rigidBody2dComponent.velocity = Vector2.zero; } // Если нажата клавиша прыжка и персонаж касается земли - прыгаем if (jumpInput > 0 && collider2dComponent.IsTouchingLayers(ground)) { rigidBody2dComponent.velocity = new Vector2(rigidBody2dComponent.velocity.x, playerVelocity.y); } // Вызываем менеджер анимаций SetAnimationState(); }

Для Player Velocity проставлены значения по-молчанию. Вы можете использовать их, либо подставить свои.

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

CameraBehaviour

В CameraBehaviour ограничение движения камеры теперь тоже задаётся через Vector2 - нужно выбрать координаты левого нижнего и правого верхнего углов.

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

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

Кстати. Вопрос о том, есть ли какие то другие решения для ограничения движения камеры остаётся открытым. Наверняка как-то можно задать програмно, или при помощи какого-то инструмента.

Добавляем и анимируем собираемые монетки

Находим необходимый спрайт по пути Assets/BayatGames/Free Platform Game Assets/Coin Animation/png/2x/image 1.png и добавляем его в сцену.

Сразу переименуем нужный объект в Coin.

Как оказалось, монетка сильно больше персонажа. Исправим это.

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

Ткнём на наш спрайт (именно спрайт, а не игровой объект Coin), и при помощи шифта выделяем все спрайты с монетами в папке.

Ставим значение Pixels Per Unit на 256 и жмякаем apply.

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

Превосходно.

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

Создадим в Assets/Animations новую анимацию c именем coinRoll, и привяжем её к объекту Coin, перетянув на Coin в иерархии.

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

В опциях coinRoll проставим галочку на Loop Time, чтобы анимация не заканчивалась.

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

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

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

Проверяем.

Монета вращается, но хочу попробовать добавить ей движение по вертикали вверх - вниз для большей динамики.

Добавим вертикальное "плавание" монеты

Если вы хотите полностью понять код движения монеты, то изучите ссылки ниже =)

docs.unity3d.com
Unity - Scripting API: Mathf.Lerp
docs.unity3d.com
Unity - Scripting API: Mathf.PingPong
stackoverflow.com
What does Unity's Mathf.PingPong actually do?

Создадим скрипт CoinBehaviour, и привяжем его к нашей монете.

В скрипте добавим специальный слайдер для выбора дистанции, которую будет проходить монета при движении.

// 0.1 - минимальное значение, 1 - максимальное [Range(0.1f, 1.0f)] public float verticalMovementDistance = 0.30f; // Изначальное расположение объекта по оси Y private float initialCoinVerticalPosition;

В Unity это будет выглядеть так:

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

В хуке Start получим текущее значение вертикального расположения монеты, и инициализируем этим значением переменную initialCoinVerticalPosition.

/** * Start **/ void Start() { // Получаем изначальное положение объекта по оси ординат initialCoinVerticalPosition = transform.position.y; }

Отлично. Изначальное положение монеты у нас есть. Осталось добавить само движение.

Для этого добавляем метод CalculateCoinVerticalPosition, который мы вызываем в хуке Update.

/** * Update **/ void Update() { // Обновляем позицию монеты каждый фрейм CalculateCoinVerticalPosition(); } // Рассчитываем текущее положение объекта void CalculateCoinVerticalPosition() { // Расчет значения Y float coinVerticalPosition = Mathf .Lerp( initialCoinVerticalPosition - (verticalMovementDistance / 2), initialCoinVerticalPosition + (verticalMovementDistance / 2), Mathf.PingPong(Time.time, 1) ); // Присваиваем новое значение позиции объекта по оси Y transform.position = new Vector3(transform.position.x, coinVerticalPosition, transform.position.z); }

Проверим, как всё работает.

При изменении значения, монета проделывает больший, или меньший путь. Успех =)

Монета должна исчезнуть, когда её соберёт игрок

Добавим объекту Player тэг, а затем применим его.

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

Теперь перейдем к объекту Coin.

Добавим Box Collider 2D (для расчета столкновений).

Отмечаем наш Box Collider, как триггер (Is Trigger), чтобы монета не сдвигалась и не оказывала физического воздействия на игрока при столкновении.

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

Настроим его чуть меньше по ширине - когда монета стоит ребром, она становится уже.

Кстати, я ведь могу изменить ширину коллайдера програмно, относительно ширины спрайта, в соответствии с текущей анимацией? Надо попробовать.

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

Теперь добавим проверку на столкновения в CoinBehaviour.

// Активация триггера при попадании в него объекта void OnTriggerEnter2D(Collider2D collision) { /** * Проверяем, тэг объекта, активировавшего триггер * Если его тэг "Player", то условия выполнено **/ if (collision.gameObject.tag == "Player") { // Уничтожаем наш объект Destroy(gameObject); } }

Теперь монета должна исчезать при столкновении с игроком.

Иии... Все работает.

Код текущей части доступен здесь.

Пока не уверен, что будет в следующий раз. Идея уже есть, но она пока в разработке =) Нужно подробнее изучить вопрос.

#unity