unity3d C# Unity二维平台生成器|人物控制器走在空中后,双跳和打击敌人在空中

qvsjd97n  于 2022-11-16  发布在  C#
关注(0)|答案(1)|浏览(145)

我有一个2D角色控制器和控制器的一部分是双跳的能力,但如果我的球员击中敌人时,在空中后,双跳或下斜线攻击的球员开始走在一条直线在空中,我假设我错过了地面检查,但不知道我是否可以有任何帮助,请:
CS代码为:

public class PlayerController : MonoBehaviour
{
    [Header("Input")]
    public float jumpHoldTime = 0.3f;
    float horizontalInput;
    float lastHorizontalInput;
    bool dead = false;

    [Header("Movement")]
    public Animator anim;
    public float moveSpeed = 5.0f;
    float currentMove = 0f;
    public bool facingRight = true;
    private Rigidbody2D rb;
    Vector2 finalMovement;
    bool runMovement = false;
    bool isMoving = false;

    [Header("Vertical Movement")]
    public int jumpCounter = 2;
    public float jumpSpeed = 5f;
    public bool inAir = true;
    public bool canDoubleJump = false;
    bool jumpHeld = false; 

    [Header("Gravity")]
    public float upGravity = -16f;
    public float downGravity = -20f;
    public float jumpHoldGravity = -5f;
    public float maxFallSpeed = -10f;
    float currentGravity = 0f;

    [Header("Col Handler")]
    public bool wallRight = false;
    public bool wallLeft = false;
    Collider2D currentGround;
    Collider2D leftWall;
    Collider2D rightWall;

    [Header("Attack")]
    public Transform attackPointRight;
    public Transform attackPointDown;
    public float attackRange = 0.5f;
    public int attackDamage = 1;
    public float attackRate = 2f;
    private float nextAttackCount = 0f;

    private bool attackingForward = true;
    public LayerMask enemyLayer;

    // Start is called before the first frame update
    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        anim = GetComponent<Animator>();
    }

    // Update is called once per frame
    void Update()
    {
        if(dead)
        {
            return;
        }

        GetInput();

    }

void GetInput() 
    {
        horizontalInput = Input.GetAxis("Horizontal");

        if(horizontalInput != 0 && lastHorizontalInput == 0) // move if input on current frame
        {
            isMoving = true;
            anim.SetBool("Moving", true);
        }
        if(horizontalInput == 0 && lastHorizontalInput != 0) // stop when movement ends on frame
        {
            isMoving = false;
            anim.SetBool("Moving", false);
        }     

        if(horizontalInput > 0f && !facingRight || horizontalInput < 0f && facingRight)
        {
            dirFlip();
        }

        if(Input.GetButtonDown("Jump"))
        {
            Jump();       
        }
        
        lastHorizontalInput = horizontalInput;
    }

    void dirFlip()
    {
        facingRight = !facingRight;
        transform.Rotate(transform.up, 180f);
    }

    void Jump()
    {   
        if(canDoubleJump)
        {
            jumpCounter -= 1;
        }

        if(jumpCounter < 0 || (inAir && !canDoubleJump))
        {
            return;
        }
        inAir = true;
        anim.SetTrigger("Jump");
        anim.SetBool("InAir", true);
        currentGravity = jumpSpeed;
        StartCoroutine(JumpHoldRoutine());

        
    }

    IEnumerator JumpHoldRoutine()
    {
        jumpHeld = true;
        float timer = 0f;
        while(timer < jumpHoldTime && Input.GetButton("Jump"))
        {
            timer += Time.deltaTime;
            yield return null;
        }
        jumpHeld = false;
    }

    private void FixedUpdate() 
    {
        if(inAir)
        {
            setMovement();
            if(jumpHeld)
            {
                currentGravity += jumpHoldGravity * Time.deltaTime;
            }

            else
            {
                if(currentGravity > 0f) 
                {
                    currentGravity += upGravity * Time.deltaTime;
                }

                else if(currentGravity <= 0f)
                {                  
                    currentGravity += downGravity * Time.deltaTime;
                }
            }

            currentGravity = Mathf.Clamp(currentGravity, maxFallSpeed, jumpSpeed);
            finalMovement.y = currentGravity;

        }

        if(isMoving)
        {
            setMovement();
            currentMove = horizontalInput * moveSpeed;
            
            if(currentMove > 0f && wallRight || currentMove < 0f && wallLeft || wallRight)
            {
                currentMove = 0f;
            }
            
            finalMovement.x = currentMove;
        }

        if(runMovement)
        {
            rb.MovePosition((Vector2)transform.position + finalMovement * Time.deltaTime);
            runMovement = false;
        }

    }

    void setMovement() 
    {
        if(!runMovement) 
        {
            runMovement = true;
            finalMovement = Vector2.zero;
        }
    }

    private void OnCollisionEnter2D(Collision2D collision) 
    {
       ColliderDistance2D collDist = collision.collider.Distance(GetComponent<Collider2D>());
       Debug.DrawRay(collDist.pointA, collDist.normal, Color.black, 1f);

       if(collision.collider.tag == "Enviro")
       {
            if(collDist.normal.y > 0.1f) // On ground to reset double jump
            {
                jumpCounter = 2;
            }

            if(collDist.normal.y > 0.1f) // Ground check
            {
                Ground(collision.collider);
            }
            if(collDist.normal.y < -0.1f) // ceiling
            {
                currentGravity = 0f;
                jumpHeld = false;
            }
            if(collDist.normal.x < -0.9f) // right wall
            {
                wallRight = true;
                rightWall = collision.collider;
            }
            if(collDist.normal.x > 0.9f) 
            {
                wallLeft = true;
                leftWall = collision.collider;
            }
       } 
       else if(collision.collider.tag == "Rat")
       {
            inAir = false;
            Jump();
            GetComponent<Health>().TakeDamage(1);
       }
       else if(collision.collider.tag == "Ghost")
       {
            inAir = false;
            Jump();
            GetComponent<Health>().TakeDamage(1);
       }
       else if(collision.collider.tag == "LavaB")
       {
            inAir = false;
            Jump();
            GetComponent<Health>().TakeDamage(1);
       }
       else if(collision.collider.tag == "BouncySpikeBall")
       {
            inAir = false;
            Jump();
       }
       else if(collision.collider.tag == "Skeleton")
       {
            inAir = false;
            Jump();
            GetComponent<Health>().TakeDamage(1);
       }
    }

    void Ground(Collider2D newGround) 
    {
        inAir = false;
        currentGravity = 0f;
        currentGround = newGround;
        anim.SetBool("InAir", false);
    }

    private void OnCollisionExit2D(Collision2D collision) // no longer collidiing with object
    {
        if(collision.collider.tag == "Enviro")
        {
            if(collision.collider == currentGround) 
            {
                if(!inAir)
                {
                    inAir = true;
                    currentGround = null;
                    anim.SetTrigger("Jump");
                    anim.SetBool("InAir", true);
                }
            }
            if(collision.collider == rightWall)
            {
                rightWall = null;
                wallRight = false;
            }
            if(collision.collider == leftWall)
            {
                leftWall = null;
                wallLeft = false;
            }
        }
    }
}

我很抱歉,这是有点长,我削减了部分是关于攻击或一些无关的东西,试图限制有多少在这里。
基本上,如果我双跳,然后击中/向下击中或接触敌人,而我仍然在空中我的球员冻结在该轴,只能左右移动,但动画仍然工作正常。
有点困惑,这需要一些帮助,请,也让我知道,如果我没有给足够的信息的问题:)
我试过在击中后切换inAir布尔,但它似乎对这个问题没有帮助。我希望球员只是再次下降,而不是停留在空中移动

owfi6suc

owfi6suc1#

你可以让你的玩家在击中敌人的时候,用很小的力量把他往上推rb.addforce,然后跳格(jumpheld或jumpcounter)会被复位。

相关问题