Цель: Улучшение контроллера персонажа и добавление функции двойного прыжка.



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

Настройка сцены (резюме)

Для этой сцены у меня есть примитивная капсула в качестве игрока, пять кубов, масштабированные как платформы, и три сферы вести себя как предметы коллекционирования.

  • Player Capsule Я создал пустой объект для игрока и установил его в начале координат. Этот пустой объект будет обрабатывать всю логику и движение. Затем внутри родительского объекта я добавил визуальные элементы, такие как капсула.

Затем я добавил новую систему ввода и синематограф. Затем я настроил карту действий игрока и добавил два действия: движение и прыжок.

  • Move отправляет vector2 всякий раз, когда нажимается A (влево) или D (вправо).

Скрипт ввода игры

Обрабатывает ввод с клавиатуры и передает значения игроку

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameInput : MonoBehaviour
{
    private ActionMaps _input;
    private void Awake()
    {
        _input = new ActionMaps();
    }

    private void OnEnable()
    {
        _input.Player.Enable();
    }

    public Vector2 GetMovementVectorNormalized() 
    {
        Vector2 _direction = _input.Player.Move.ReadValue<Vector2>();
        _direction = _direction.normalized;
        return _direction;
    }

    public bool IsJumping() 
    {
        if (_input.Player.Jump.IsPressed())
            return true;
        else return false;
    }
}

Реализовать двойной прыжок

Первый прыжок проверяет, находится ли игрок на земле, и устанавливает логическую переменную для двойного прыжка в false. Таймер создан для предотвращения случайного прыжка, если пробел удерживается слишком долго.

if (_groundPlayer == true && _gameInput.IsJumping()) {
            _yVelocity += _jumpStrength;
            _doubleJump = false;
            _jumpDelay = Time.time + 0.3f;
            
        }

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

 else if(_groundPlayer == false) 
        {
            if (!_doubleJump && _gameInput.IsJumping() && Time.time > _jumpDelay) 
            {
                _doubleJump = true;
                if(_yVelocity < 0) { 
                    _yVelocity = 0;
                    _yVelocity += 5f;
                }
                else
                    _yVelocity += 5f;

            }

Краткое объяснение символов yVelocity (ось Y). По умолчанию к телу игрока постоянно применяется сила -9,8, будь то на земле или в воздухе. Когда игрок прыгает, положительная сила 17 добавляется в направлении Y (yVelocity = 7,2). Двойной прыжок добавляет +5 при повторном нажатии пробела.

                if(_yVelocity < 0) { 
                    _yVelocity = 0;
                    _yVelocity += 5f;
                }
                else
                    _yVelocity += 5f;

Одна проблема заключается в том, что когда игрок падает в течение длительного периода времени, yVelocity будет отрицательным значением (yVelocity = 7,2-(-9,8 в секунду))с максимальной скоростью падения -20f (mathf.clamp). Чтобы сделать двойной прыжок последовательным, я сбрасываю _yVelocity на 0, если значение отрицательное. Совершайте плавные прыжки независимо от того, как долго вы падали. Как вы можете видеть ниже!

Метод полного прыжка

  private void Update()
    {

        _groundPlayer = _controller.isGrounded;


        if (_groundPlayer == true)
        {
            _controller.Move(Vector3.zero);
            _yVelocity = -_gravity;
        }

        if (_groundPlayer == true && _gameInput.IsJumping()) {
            _yVelocity += _jumpStrength;
            _doubleJump = false;
            _jumpDelay = Time.time + 0.3f;
            
        }
        else if(_groundPlayer == false) 
        {
            if (!_doubleJump && _gameInput.IsJumping() && Time.time > _jumpDelay) 
            {
                _doubleJump = true;
                if(_yVelocity < 0) { 
                    _yVelocity = 0;
                    _yVelocity += 5f;
                }
                else
                    _yVelocity += 5f;

            }

        _yVelocity -= _gravity * Time.deltaTime;

        }

        var _yMaxVelocity = Mathf.Clamp(_yVelocity, -20, 100f);
        
        Vector3 _direction = _gameInput.GetMovementVectorNormalized();
        Vector3 _xVelocity = _direction * _speed;
        
        Vector3 _movement = new Vector3(_xVelocity.x, _yMaxVelocity, 0);
        _controller.Move(_movement * Time.deltaTime);

    }