Как я могу проверить, находится ли мой 2D персонаж в эфире в Unity2D? - PullRequest
0 голосов
/ 23 февраля 2020

Так что я пытаюсь заставить моего 2D персонажа прыгать. Если я бегаю по земле, она работает отлично, но когда я сталкиваюсь со стеной, она глючит: я могу прыгать даже в воздухе. Я пытался решить это с помощью переменной bool, но это не сработало. Я подумал о том, чтобы проверить, находится ли игрок в воздухе, а затем установить для переменной is_on_ground значение false. Очевидно, что игрок должен прыгать, только если он находится на земле. Мой код следующий:

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

public class PlayerMovement : MonoBehaviour
{
    private bool canJump = false;
    public SpriteRenderer sr;
    private bool facingRight;
    private Animator animator;
    private bool is_on_ground;
    public Button leftBtn;
    public Button rightBtn;
    public Button jumpBtn;
    public float max_velocity;
    public float velocity;
    public float jump_scalar;
    private Rigidbody2D rb;
    private float x_movement;
    private Vector2 movement;
    void Start() {
        canJump = true;
        facingRight = true;
        animator = gameObject.GetComponent<Animator>();
        leftBtn.onClick.AddListener(moveLeft);
        rightBtn.onClick.AddListener(moveRight);
        jumpBtn.onClick.AddListener(jump);
        rb = gameObject.GetComponent<Rigidbody2D>();
    }
    private void FixedUpdate() {
        if (rb.velocity.magnitude < max_velocity) {
            movement = new Vector2(x_movement, 0);
            rb.AddForce(movement * velocity);
        }
    }
    private void OnCollisionEnter2D(Collision2D collision) {
        if (CollisionIsWithGround(collision)) {
            animator.SetBool("isJumping", false);
            canJump = true;
        }
        if (collision.collider.tag == "wall") {
            canJump = false;
        }
        is_on_ground = true;

    }
    private void OnCollisionExit2D(Collision2D collision) {
        if (!CollisionIsWithGround(collision)) {
            is_on_ground = false;
        }
        if (collision.collider.tag == "wall") {
            is_on_ground = true;
            canJump = true;
        }
    }
    private bool CollisionIsWithGround(Collision2D collision) {
        bool is_with_ground = false;
        foreach (ContactPoint2D c in collision.contacts) {
            Vector2 collision_direction_vector = c.point - rb.position;
            if(collision_direction_vector.y < 0) {
                is_with_ground = true;
            }
        }
        return is_with_ground;
    }
    public void moveLeft() {
        if (is_on_ground) {
            animator.SetBool("isJumping", false);
        }
        animator.SetBool("isRunning", true);
        sr.flipX = true;
        facingRight = false;
        x_movement = -1;
    }
    public void onRelease() {
        animator.SetBool("isRunning", false);
        x_movement = 0;
        if(is_on_ground) {
            animator.SetBool("isJumping", false);
            rb.velocity = Vector3.zero;
        }
    }
    public void moveRight() {
        if (is_on_ground) {
            animator.SetBool("isJumping", false);
        }
        if (!facingRight) {
            sr.flipX = false;
            facingRight = true;
            animator.SetBool("isRunning", true);
        } else {
            animator.SetBool("isRunning", true);
        }
        x_movement = 1;
    }
    public void jump() {
        if(is_on_ground) {
            if (canJump) {
                animator.SetBool("isJumping", true);
                Vector2 jumpForce = new Vector2(0, jump_scalar * 100);
                rb.AddForce(jumpForce);
            }
        }
    }
}

проблема выглядит следующим образом

Ответы [ 2 ]

0 голосов
/ 23 февраля 2020

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

Вам нужно будет добавить пустой игровой объект проверки земли как ребенка вашего игрока и расположить его трансформацию на ноги игрока. Затем вам нужно определить, какие слои считаются землей в инспекторе для m_WhatIsGround LayerMask.

Затем в FixedUpdate() проверьте, находится ли преобразование проверки земли в пределах некоторого радиуса от земли.

// A mask determining what is ground to the character
[SerializeField] private LayerMask m_WhatIsGround;

// A position marking where to check if the player is grounded.
[SerializeField] private Transform m_GroundCheck;

// Radius of the overlap circle to determine if grounded
const float k_GroundedRadius = 0.3f;

private void FixedUpdate() {
    is_on_ground = false;

    // The player is grounded if a circlecast to the groundcheck position hits anything designated as ground
    // This can be done using layers instead but Sample Assets will not overwrite your project settings.
    Collider2D[] colliders = Physics2D.OverlapCircleAll(m_GroundCheck.position, k_GroundedRadius, m_WhatIsGround);
    for (int i = 0; i < colliders.Length; i++) {
        if (colliders[i].gameObject != gameObject) {
            is_on_ground = true;
        }
    }
}

Учебное пособие по этому методу можно найти в этом видео Брэки .

0 голосов
/ 23 февраля 2020

Вы можете выполнить Physics2d.Raycast на пол в каждом FixedUpdate. Когда диапазон до ближайшего объекта меньше 0,01 или что-то в этом роде, вы можете проверить, является ли он минимальным, и если он установлен, то установить is_on_ground = true, а если нет, выполнить is_on_ground = false

Пример:

float raycastDistance = 0.05f;
RaycastHit2D hit = Physics2D.Raycast(transform.position, -Vector2.up, raycastDistance);
if (hit.collider != null && hit.transform.gameObject.layer == LayerMask.NameToLayer("ground"))
    is_on_ground = true;
} else {
    is_on_ground = false;
}

Это должно работать. Очевидно, что в этом примере вы должны определить слой с именем ground и добавить его к каждой земле.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...