Итак, вы хотите создать свой собственный файтинг, такой как Smash Bros. или мультиверсус, но не знаешь с чего начать? Что ж, вы пришли в нужное место. В этой серии, которая будет выпущена примерно через неделю, мы расскажем об основах запуска и запуска вашей игры, после чего вы сможете изменить и отредактировать игру, чтобы сделать ее своей собственной.

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

Настройка проекта единства

Для начала создайте новый проект Unity 2D, как показано на изображении, и назовите его как хотите. (Обратите внимание, что в будущем вы, возможно, захотите перейти к 3D-проекту, чтобы использовать 3D-анимацию вместо 2D-спрайтов)

Внутри проекта щелкните правой кнопкой мыши внутри иерархии слева от экрана и выберите «Создать пустой». Измените имя этого объекта на «Игрок». Теперь щелкните правой кнопкой мыши «Проигрыватель» и выберите «2D-объекты» › «Спрайты» › «Квадрат». Убедитесь, что квадрат находится в центре игрока. Сделайте квадрат прямоугольной формы, чтобы он был больше в высоту, чем в ширину, и сделайте его любого цвета, который вам нравится (или пока оставьте его белым). Наконец, создайте пустой объект и расположите его на нижнем краю плеера. Назовите этот объект «GroundCheck». Наконец, ваш экран должен выглядеть примерно так:

Теперь добавляем землю. Снова щелкните правой кнопкой мыши внутри иерархии и на этот раз выберите «2D-объекты» › «Спрайты» › «Квадрат». Внутри инспектора щелкните раскрывающийся список тегов, добавьте тег…, затем щелкните маленький + под серым полем в разделе «Теги». Назовите этот тег «платформа». Вернитесь, чтобы выбрать квадрат, сделать его ширину равной размеру экрана и расположить внизу экрана. Это будет наша земля. Теперь нажмите «Добавить компонент» и выберите «Box Collider 2D». Обратите внимание на 2D в конце. Теперь создайте второй квадрат, измените его размер и переместите так, чтобы он выглядел как платформа. Отредактируйте коллайдер с помощью кнопки «Редактировать коллайдер» и сделайте его тонким, но не слишком (позже объясним, почему это так). Вы получите экран, который выглядит примерно так.

Добавление движения игроку

Как вы, вероятно, заметите, когда мы нажимаем кнопку воспроизведения, ничего не происходит. Нам нужно создать скрипт, чтобы игрок двигался!

Таким образом, нажмите на объект «Игрок» и нажмите «Добавить компонент». Введите characterMovement или что-то в этом роде и нажмите новый скрипт. Дважды щелкните созданный скрипт, чтобы открыть его в предпочитаемом вами редакторе кода. Сгенерированный файл будет выглядеть примерно так:

Затем мы добавим public float runSpeed; в начало нашего класса, так как это будет значение, которое мы можем редактировать из редактора проекта, чтобы быстро настроить и отредактировать его. Это будет значение, равное скорости бега персонажа. Затем нам нужно добавить private Vector2 playerVel;, Vector2, содержащий скорость игрока по осям x и y.

Внутри обновления мы добавляем playerVel.x = runSpeed * Input.GetAxisRaw("Horizontal"); Это установит нашу скорость x равной нашему горизонтальному вводу. GetAxisRaw вернет число от -1 (слева) до 1 (справа) для горизонтального ввода при использовании джойстика или просто -1,0 (ничего), 1 для клавиатуры. При использовании джойстика промежуточные значения 0,5, например, заставят персонажа двигаться медленнее вправо, если джойстик не полностью нажат, что позволит более точно двигаться.

Наконец, мы добавляем нашу скорость x к положению игрока в каждом кадре, как показано: gameObject.transform.position += playerVel.x * Vector3.right * Time.deltaTime; здесь мы умножаем скалярное значение playerVel.x на Vector3.right (1,0,0), так что мы изменяем только игровые объекты x- position (чего мы не можем сделать с gameObject.transform.position.x, так как он доступен только для чтения). Затем мы умножаем это значение на Time.deltaTime, время в секундах, которое потребовалось для рендеринга последнего кадра, или равное 1/fps. Это означает, что мы делим нашу x-скорость на количество кадров в секунду, так что если наша функция обновления (вызываемая один раз за кадр) обновляется много раз, мы перемещаемся на меньшую долю в каждом кадре (больше кадров в секунду, что означает, что Time.deltaTime меньше, и поэтому общая скорость меньше), или если функция обновления вызывается меньше раз (меньше кадров в секунду), мы все равно движемся с той же скоростью. После добавления значения runSpeed ​​в инспекторе (например, 5) результат должен выглядеть следующим образом:

Добавление гравитации и обнаружения столкновений

Конечно, нам нужно, чтобы игрок падал каждый кадр, что очень просто. Добавьте переменную public float gravity; в свой класс, чтобы изменить силу гравитации. Теперь под предыдущим кодом в вашей функции обновления добавьте строки playerVel.y += gravity*Time.deltaTime; и gameObject.transform.position += playerVel.y * Vector3.up * Time.deltaTime;. Вы можете заметить, что мы дважды умножаем нашу гравитацию на время, потому что гравитация — это ускорение m/s^2 . Однократное умножение на время преобразует его в скорость m/s^2 * s = m/s , которую мы добавляем к скорости игрока по мере того, как он изменяется/ускоряется на эту скорость, а затем мы снова умножаем эту скорость на m/s * s = m, чтобы сделать ее пройденным расстоянием, что является другим способом мышления. о частоте кадров не зависит Time.deltaTime, так как delta означает изменение. Наш код теперь выглядит так:

Однако при запуске игры вы можете заметить (не забудьте установить значение гравитации в инспекторе примерно на -9), что наш игрок падает прямо сквозь землю, чего мы не хотим. Теперь мы реализуем обнаружение столкновений:

Создайте новый private bool groundedPlayer;, который будет содержать значение, указывающее, заземлен ли игрок. Создайте также public Transform groundCheck; и public GameObject sprite;. Теперь под кодом перемещения проигрывателя по горизонтали добавьте следующий фрагмент кода:

Затем мы хотим изменить playerVel.y += gravity * Time.deltaTime; на:

if (groundedPlayer) {
    playerVel.y = 0f;
} else {
    playerVel.y += gravity * Time.deltaTime;
}

Теперь вернитесь к проекту Unity и добавьте дочерний объект GroundCheck к преобразованию проверки земли и квадратный дочерний объект к игровому объекту спрайта.

Запуск проекта теперь дает желаемый результат, останавливая персонажа всякий раз, когда мы касаемся земли.

Добавляем базовые прыжки

Добавьте public float jumpHeight;, который будет определять, как высоко мы будем прыгать.

Теперь внутри нашего предыдущего if (groundedPlayer) { добавьте следующий оператор if, заменяющий playerVel.y = 0f;:

if (Input.GetButtonDown("Jump")) {
    playerVel.y += Mathf.Sqrt(jumpHeight * -2.0f * gravity);
} else {
    playerVel.y = 0f;
}

Как это работает через физику! Вот краткое объяснение для тех, кто хочет знать больше:

Потенциальная гравитационная энергия (на вершине) = масса × гравитация × Δвысота

Кинетическая энергия (в начале) = 1/2 × масса × скорость²

KE в начале = GPE в вершине

масса × гравитация × Δвысота = 1/2 × масса × скорость²

Отмена массы:

гравитация × Δвысота = 1/2 × скорость²

Переставляя, чтобы найти начальную скорость:

скорость = sqrt( 2 × гравитация × Δвысота)

Теперь мы изменили гравитацию в инспекторе на -13,5, так как это дало лучшие результаты.

Далее во второй части: трюки с невидимыми прыжками

Во многих наших любимых играх реализованы невидимые трюки, о которых мы даже не догадываемся! Вот некоторые из них, которые мы реализуем:

  • apex boost — замедлить падение и увеличить скорость x на вершине прыжка
  • буфер прыжка — позволяет вводить входные данные прыжка за несколько кадров до касания земли
  • время койота — разрешить ввод прыжка через несколько кадров после отрыва от земли
  • Быстрое падение — сделайте наклон персонажа больше, чем его наклон прыжка.
  • Переменная высота прыжка — в зависимости от того, как долго была нажата кнопка прыжка, мы прыгаем выше или ниже.

Не забудьте подписаться на меня, чтобы не пропустить эту еженедельную серию!