Загрузка...

Как сделать нормальный прыжок юнити?

Тема в разделе C# создана пользователем Plotick 27 дек 2024. 217 просмотров

Загрузка...
  1. Plotick
    Plotick Автор темы 27 дек 2024 12 768 21 окт 2022
    Начал изучение C# и юнити в целом неделю назад, так что я совсем еще чайник. В общем, всё работает почти идеально, не учитывая того, что через каждые 2-3 раза прыжок просто отказывается срабатывать, как бы упорно я не ебашил по пробелу.
    Подозреваю, что проблема связана с проверкой на касание земли, но без нее прыжками можно буквально взлететь. Как пофиксить? :morda:
    CSHARP
    using UnityEngine;

    public class PlayerMovementJump : MonoBehaviour
    {
    public Rigidbody rb;
    public float forwardForce = 2000f;
    public float sidewaysForce = 500f;
    public float jumpForce = 5f;
    public float fallForce = -15f;
    private bool isGrounded = true;

    void FixedUpdate()
    {
    // Постоянное движение вперед
    rb.AddForce(0, 0, forwardForce * Time.deltaTime);

    // Движение вправо
    if (Input.GetKey("d"))
    {
    rb.AddForce(sidewaysForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
    }

    // Движение влево
    if (Input.GetKey("a"))
    {
    rb.AddForce(-sidewaysForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
    }

    // Проверка прыжка
    if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
    {
    this.jump(); // Вызов метода jump
    }

    rb.AddForce(0, fallForce, 0); // Ускоряет падение объекта

    // Проверка падения
    if (rb.position.y < -1f)
    {
    FindObjectOfType<GameManager>().EndGame();
    }
    }

    private void jump()
    {
    rb.AddForce(0, jumpForce, 0, ForceMode.VelocityChange);
    isGrounded = false; // Запретить прыжок до следующего касания земли
    }

    private void OnCollisionEnter(Collision collision)
    {
    if (collision.gameObject.CompareTag("Ground"))
    {
    isGrounded = true; // Разрешить прыжок
    }
    }
    }
     
    1. Plotick Автор темы
      СвятойОтец, я вчера час с ним провозился, ничего толкового не выдал
  2. СвятойОтец
    Проблема может быть связана с тем, что флаг isGrounded не успевает корректно обновиться при быстром взаимодействии между прыжком и касанием земли. Это может происходить, например, из-за микроскопических временных лагов или особенностей физического взаимодействия объекта с поверхностью.



    Вот несколько шагов для устранения проблемы:



    1. Уточните проверку касания земли



    Добавьте проверку слоя или тегов для большей точности. Иногда коллайдер объекта может вступить в контакт с чем-то, что не является “землёй”.



    if (collision.gameObject.CompareTag("Ground"))

    {

    isGrounded = true;

    }



    2. Добавьте минимальную задержку между прыжками



    Вместо использования только флага isGrounded, можно добавить небольшой таймер, чтобы избежать ложных срабатываний:



    private float jumpCooldown = 0.1f; // Минимальная задержка между прыжками

    private float lastJumpTime = 0f;



    private void jump()

    {

    if (Time.time - lastJumpTime >= jumpCooldown)

    {

    rb.AddForce(0, jumpForce, 0, ForceMode.VelocityChange);

    isGrounded = false;

    lastJumpTime = Time.time;

    }

    }



    3. Используйте луч (Raycast) для проверки соприкосновения с землёй



    Физическая проверка с помощью луча обычно работает более надёжно, чем полагаться на события OnCollisionEnter. Пример:



    Добавьте проверку в метод FixedUpdate:



    private void CheckIfGrounded()

    {

    float rayLength = 1.1f; // Длина луча чуть больше радиуса коллайдера

    isGrounded = Physics.Raycast(transform.position, Vector3.down, rayLength);

    }



    Замените вызовы обновления isGrounded:



    void FixedUpdate()

    {

    CheckIfGrounded();



    // Движение и прыжок остаются теми же

    }



    4. Добавьте слои для точной проверки земли



    Убедитесь, что у объекта “земля” установлен соответствующий слой (например, “Ground”), и используйте его в проверке Raycast:



    LayerMask groundLayer; // Назначьте слой через инспектор



    private void CheckIfGrounded()

    {

    float rayLength = 1.1f;

    isGrounded = Physics.Raycast(transform.position, Vector3.down, rayLength, groundLayer);

    }



    5. Проверка физического слоя коллайдеров



    Проверьте размеры и расположение коллайдеров для “земли” и игрока, чтобы избежать ложных срабатываний. Убедитесь, что игрок действительно касается земли.



    Итоговый код:



    Вот обновлённая версия с улучшенной проверкой касания земли:



    using UnityEngine;



    public class PlayerMovementJump : MonoBehaviour

    {

    public Rigidbody rb;

    public float forwardForce = 2000f;

    public float sidewaysForce = 500f;

    public float jumpForce = 5f;

    public float fallForce = -15f;

    public LayerMask groundLayer;



    private bool isGrounded = true;

    private float jumpCooldown = 0.1f;

    private float lastJumpTime = 0f;



    void FixedUpdate()

    {

    // Постоянное движение вперед

    rb.AddForce(0, 0, forwardForce * Time.deltaTime);



    // Движение вправо

    if (Input.GetKey("d"))

    {

    rb.AddForce(sidewaysForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange);

    }



    // Движение влево

    if (Input.GetKey("a"))

    {

    rb.AddForce(-sidewaysForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange);

    }



    // Проверка состояния земли

    CheckIfGrounded();



    // Прыжок

    if (Input.GetKeyDown(KeyCode.Space) && isGrounded)

    {

    jump();

    }



    rb.AddForce(0, fallForce, 0);



    // Проверка падения

    if (rb.position.y < -1f)

    {

    FindObjectOfType<GameManager>().EndGame();

    }

    }



    private void jump()

    {

    if (Time.time - lastJumpTime >= jumpCooldown)

    {

    rb.AddForce(0, jumpForce, 0, ForceMode.VelocityChange);

    isGrounded = false;

    lastJumpTime = Time.time;

    }

    }



    private void CheckIfGrounded()

    {

    float rayLength = 1.1f; // Длина луча чуть больше радиуса коллайдера

    isGrounded = Physics.Raycast(transform.position, Vector3.down, rayLength, groundLayer);

    }

    }



    6. Совет: настройка слоя “Ground”



    Убедитесь, что слой “Ground” назначен всем объектам, которые игрок может использовать для прыжка. Выберите объект в Unity, установите слой в поле Layer, а затем присвойте его переменной groundLayer в инспекторе.



    Этот подход должен устранить проблему с нерегулярным срабатыванием прыжков.
     
  3. Plotick
    Plotick Автор темы 27 дек 2024 12 768 21 окт 2022
    GetKeyDown возвращает true только в кадре, в котором была нажата клавиша. FixedUpdate не срабатывает в каждом кадре, поэтому он может пропустить тот, в котором была нажата кнопка. Нужно было просто изменить FixedUpdate на Update :ameat:
     
Top