Переменная isGounded не меняется на false после начального перехода в Unity - PullRequest
2 голосов
/ 22 марта 2020

Обзор

Используя Unity2D 2019.3.5, я создаю платформерную игру, используя C#. Я реализовал raycast, чтобы определить, когда мой игрок касается земли, и попытался сделать это только так, чтобы игрок мог прыгнуть только один раз.

Проблема

Хотя я думал, что запрограммирован Мой персонаж прыгнул один раз, после первого прыжка, движок Unity все еще показывает галочку для моей переменной isGounded и превращается в ложное (не проверяется) после второго прыжка, прежде чем упасть на землю.

Мой код

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

public class Player_Controller : MonoBehaviour
{

    public int playerSpeed = 10;
    public int playerJumpPower = 1250;
    private float moveX;
    public bool isGrounded;
    public float distanceToBottomOfPlayer = .7f;

    // Update is called once per frame
    void Update()
    {
        PlayerMove();
        PlayerRaycast();
    }

    void PlayerMove()
    {
        // CONTROLS
        moveX = Input.GetAxis("Horizontal");
        if (Input.GetButtonDown("Jump") && isGrounded == true)
        {
            Jump();
        }

        // ANIMATIONS

        // PLAYER DIRECTION
        if (moveX < 0.0f)
        {
            GetComponent<SpriteRenderer>().flipX = true;
        }
        else if (moveX > 0.0f)
        {
            GetComponent<SpriteRenderer>().flipX = false;
        }

        // PHYSICS
        gameObject.GetComponent<Rigidbody2D>().velocity = new Vector2(moveX * playerSpeed, 
gameObject.GetComponent<Rigidbody2D>().velocity.y);
    }

    void Jump()
    {
        GetComponent<Rigidbody2D>().AddForce(Vector2.up * playerJumpPower);
        isGrounded = false;
    }

    void PlayerRaycast()
    {
        // Ray Down
        RaycastHit2D rayDown = Physics2D.Raycast(transform.position, Vector2.down);

        if (rayDown.collider != null && rayDown.distance < distanceToBottomOfPlayer && 
rayDown.collider.tag == "ground")
        {
            isGrounded = true;
        }
    }
}

Дополнительная информация

Мне пришлось изменить настройку Unity в «Правка»> «Настройки проекта»> «Физика 2D»> «Запросы запускаются в коллайдерах». Мне пришлось отключить эту настройку (снять флажок), чтобы заставить мой плеер прыгать, используя код, который я написал выше. Я знаю, что есть и другие способы заставить мой проигрыватель прыгать, но, похоже, он наиболее эффективен при сохранении читабельности кода.

Пробные решения

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

Заключительные замечания

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

Ответы [ 2 ]

1 голос
/ 23 марта 2020

Первая проблема заключается в том, что вы добавляете силу и проверяете землю в том же кадре.

Прикладная сила вычисляется в FixedUpdate или путем явного вызова метода Physics.Simulate.

Поэтому после нажатия кнопки «Прыжок» объект все еще находится на заземление до следующего кадра.

Чтобы исправить это, вы можете просто поменять порядок «move» и «raycast»

void Update()
{
    PlayerRaycast();
    PlayerMove();
}

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

void PlayerRaycast()
{
    if(GetComponent<Rigidbody2D>().velocity.y > 0)
        return;
    ...
}
1 голос
/ 23 марта 2020

Поскольку вы не можете быть уверены, что isGrounded - это false, когда вы звоните Jump().
Я думаю, что проблема заключается в этом.
Попробуйте не устанавливать isGrounded флаг при вызове Jump(). Установка isGrounded - это работа PlayerRaycast().

    void Update()
    {
        // Raycast before moving
        PlayerRaycast();
        PlayerMove();
    }

     void PlayerRaycast()
    {
        // Ray Down
        RaycastHit2D rayDown = Physics2D.Raycast(transform.position, Vector2.down);

        if (rayDown.collider != null && rayDown.collider.tag == "ground")
        {
            if( rayDown.distance < distanceToBottomOfPlayer )
            {
                isGrounded = true;
            }
            else
            {
                isGrounded = false;
            }
        }
    }

    void Jump()
    {
        GetComponent<Rigidbody2D>().AddForce(Vector2.up * playerJumpPower);
        //isGrounded = false;
    }
...