Гравитация вручную
Часть раздела Создание настоящих игр путешествия по Unity на Coddy. Урок 39 из 60.
CharacterController падает только в том случае, если ваш скрипт заставляет его падать, а реальное падение ускоряется: гравитация каждую секунду добавляет около 9.81 единицы к скорости падения. Поэтому скрипт хранит вертикальную скорость в поле, каждый кадр прибавляет к ней gravity * Time.deltaTime и перемещает контроллер на эту величину в том же вызове Move, что и при ходьбе:
public float gravity = -9.81f;
float verticalSpeed;
void Update()
{
if (controller.isGrounded && verticalSpeed < 0f)
{
verticalSpeed = -2f; // на земле: прекратить падение, сохранить лёгкое движение вниз
}
verticalSpeed += gravity * Time.deltaTime;
Vector3 move = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical")) * speed;
move.y = verticalSpeed;
controller.Move(move * Time.deltaTime);
}Time.deltaTime используется дважды для решения двух задач: gravity * Time.deltaTime — это прирост скорости за текущий кадр, а скорость, умноженная на Time.deltaTime, — расстояние, пройденное за текущий кадр. Скорость хранится в поле, потому что она должна сохраняться от кадра к кадру; локальная переменная каждый кадр снова получала бы значение 0. Падая из состояния покоя, контроллер через полсекунды движется со скоростью -4.9 единицы в секунду, а через одну секунду — со скоростью -9.81.
Сброс не менее важен, чем само падение. На полу Move останавливает контроллер, но ничто не останавливает поле: без сброса его значение продолжает расти, пока игрок стоит, и при следующем шаге с края он начнёт падать на полной скорости. Значение сбрасывается до небольшого отрицательного числа, а не до 0, чтобы каждый вызов Move по-прежнему прижимал контроллер к полу: при высокой частоте кадров смещение от гравитации за один кадр может оказаться меньше Min Move Distance, Move ничего не сделает, и isGrounded станет false. isGrounded считывается до вызова Move, поэтому оно описывает результат Move за предыдущий кадр.
Задание
СреднеДобавь дайверу гравитацию, чтобы он падал всё быстрее.
- В начале
Update(), еслиcontroller.isGroundedиverticalSpeed < 0f, установиverticalSpeed = -1f;. - Прибавь к нему
gravity * Time.deltaTimeи поддерживай его на уровне-maxFallили выше с помощьюMathf.Max. - Перед строкой
controller.Moveустановиmove.y = verticalSpeed;.
Нажми «Играть» и сойди с башни: падение ускорится до 10 единиц в секунду. Затем нажми «Проверить».
Попробуйте сами
using UnityEngine;
public class Diver : MonoBehaviour
{
public float speed = 4f;
public float gravity = -12f;
public float maxFall = 10f;
CharacterController controller;
float verticalSpeed;
void Start()
{
controller = GetComponent<CharacterController>();
}
void Update()
{
// Гравитация: сбросить verticalSpeed на земле, добавить ускорение свободного падения, ограничить скорость падения и записать результат в move.y
Vector3 move = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical")) * speed;
controller.Move(move * Time.deltaTime);
}
}
Все уроки раздела Создание настоящих игр
1Текст на экране
Холст и текстПокажем счётФорматирование чиселТаймер обратного отсчётаПовторение: спидометр4Сцены и уровни
Загрузить сценуПерезапустить уровеньСледующий уровеньСохранить между сценамиПовторение: выбор уровня2Кнопки и экраны
Кнопки и onClickЛямбдыСвязи в InspectorВключение и выключение панелейШкалы здоровьяПовторение: магазин улучшений5Сохранение с помощью PlayerPrefs
Сохранение числаЗагрузка со значением по умолчаниюРекордСохранение настроекПовторение: монеты в банке8Контроллер персонажа
CharacterController.MoveГравитация вручнуюПрыжкиТолкаем предметыДвижение в направлении взглядаПовторение: двойной прыжокПотренируйтесь самостоятельно: Песочница Unity