简体   繁体   English

如何在 Unity 中为 2D 平台游戏的双跳后添加跳转缓冲区?

[英]How can I add Jump Buffer after a Double Jump for 2D platformer in Unity?

** I'm trying to double jump mechanic for Unity 2D platformer game. ** 我正在尝试 Unity 2D 平台游戏的双跳机制。 What I want is when the character has finished the double jump and right before it landed, if we hit the any Jump button, the character will still know it is the jump input.我想要的是当角色完成二段跳并且就在它落地之前,如果我们点击任意跳转按钮,角色仍然会知道这是跳转输入。 The Coyote Jump work just fine but the Buffer Jump is not ** Coyote Jump 工作得很好,但 Buffer Jump 不是 **

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

public class Fox2 : MonoBehaviour {

    Rigidbody2D rb;
    Animator animator;

    //Public Fields
    [Range(0, 10f)] public float runSpeed=10f;
    [Range(0, 300f)]public float jumpForce=200.0f;


    #region private fields
    // A small amount of time that player is allowed to jump after leaving a platform
    private float coyoteTime = 0.25f;
    private float coyoteTimeCounter;

    // A small amount of time to detect whether player presses the Jump Buttons or not
    private float bufferTime = 0.2f;
    private float bufferTimeCounter= 0f;
    #endregion

    #region SerializeField
    [SerializeField] Collider2D headCollider;
    [SerializeField] Collider2D crouchingCollider;
    [SerializeField] Transform groundCheckCollider;
    [SerializeField] Transform ceilingCheckCollider;
    [SerializeField] LayerMask groundLayer;
    [SerializeField] LayerMask groundLayer2;// High platform
    [SerializeField] int totalJumps;
    #endregion

    #region Variables
    int availableJumps;
    // Change the current x-axis position of the character
    float horizontalValue;
    // Change the value of the speed when the player is running
    float runSpeedModifier=2f;
    // Change the value of the speed when the player is running
    float crouchSpeedModifier=0.3f;
    // Change the power of the normal jump
    float lowJumpForceModifier=0.22f;
    // The wide of "groundCheckCollider" will use 
    float groundCheckRadius=0.5f;
    // The wide of "ceilingCheckCollider" will use 
    float ceilingCheckRadius=0.2f;

    
    // By default, the Fox will facing to the right side of the screen
    bool isFacingRight=true;
    // If the Fox is on the walking state, he will be changed to running
    bool isRunning;
    // Check if the Fox is standing on the ground
    bool isGrounded;
    // Check if the Fox was standing on the ground
    bool wasGrounded;
    // Check if the Fox is underneath a platform
    bool isCeiling;
    // Check if the Fox is able to crouch if he is on the ground
    bool isCrouching;

    bool isJumping;
    // the value to indicate if player can do Multiple Jumps or not
    bool multipleJumps;
    #endregion

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

    // Update is called once per frame
    // Update will get input from the player
    void Update() {
        #region Move Input Mechanics
        //Walk and Run input
        horizontalValue=Input.GetAxisRaw("Horizontal");

        if(Input.GetKeyDown(KeyCode.LeftShift))
            isRunning=true;

        if(Input.GetKeyUp(KeyCode.LeftShift)) 
            isRunning=false;
        #endregion

        if(isGrounded)  
            coyoteTimeCounter = coyoteTime;      
        else coyoteTimeCounter -= Time.deltaTime;

        if(availableJumps == 0)
            bufferTimeCounter = bufferTime;
        else bufferTimeCounter -= Time.deltaTime; 
     
        #region Jump Input Mechanics
        if(Input.GetButtonDown("Jump"))
            Jump();  

        if(Input.GetButtonUp("Jump") && rb.velocity.y > 0)
            lowJump();
        #endregion  

        #region Crouch Input Mechanics
        if(Input.GetButtonDown("Crouch"))
            isCrouching=true;

        else if(Input.GetButtonUp("Crouch"))
            isCrouching=false;
        #endregion

         
    }
          
    // Check if the character is standing on the ground or not
    void GroundCheck() {
        wasGrounded = isGrounded;
        isGrounded=false;
        
        // Create a collider with the position of GroundCheckCollider (underneath the Fox), Radius: 0.5, 
        // and only tell the character is on the ground when he standing on the sorted ground layers
        Collider2D[] colliders=Physics2D.OverlapCircleAll(groundCheckCollider.position, groundCheckRadius, groundLayer);

        // If the colliding area between the GroundCheckCollider and the SortedGroundLayer is above 0, 
        // the character is on the ground
        if(colliders.Length> 0)
        {
            isGrounded=true;
            if(!wasGrounded)
            {
                availableJumps = totalJumps; 
                   multipleJumps=false;
            }           
        }
    
        // if the Player is not on the ground, play the Jumping animation
        // If the player is on the ground, disable the Jumping animation
        animator.SetBool("Jumping", !isGrounded);     
    }

    #region Jumping mechanics
    
    // This section will take care of the normal jumps and multiple jumps 
    void Jump()
    {   
        #region Initial Jumps Mechanics
        // If the character is not on the ground and he ism't crouching
        // let him do the initial jump
        if(!isCrouching && (isGrounded || bufferTimeCounter >= 0f))  {
            // Increase the y velocity by the amount of "jumpForce", keep x velocity the same
            rb.velocity = Vector2.up * jumpForce;
            // After the initial, set the MultipleJumps to true so he can jump multiple times if he wishes to
            multipleJumps= true;
            // Minus the number of jumps he already do the Initial Jump
            availableJumps--;
            bufferTimeCounter = 0f;
            // Add Jumping animation to the character
            animator.SetBool("Jumping", true); 
            Debug.Log("Initial Jump");
        }
        #endregion
        else
        {   
            #region Coyote Jumps Mechanics
            // But if the character is on the edge of a platform but still want to jump,
            // change the initial jump into the coyote ones.  
            if(!isCrouching && coyoteTimeCounter> 0f)
            {
                // Increase the y velocity by the amount of "jumpForce", keep x velocity the same
                rb.velocity = Vector2.up * jumpForce;
                // The same with the Initial Jump
                multipleJumps = true;
                // Minus the number of jumps he already do the Coyote Jump as the Initial ones.
                availableJumps--;
                // Add Jumping animation to the character
                animator.SetBool("Jumping", true);
                Debug.Log("Coyote Jump");
            }
            #endregion

            #region Multiple Jump Mechanics
            // After the Initial Jump or the Coyote Jump, 
            // the character will be able to perform the Multiple Jump
            // as long as the number of the availableJumps is greater than 0 
            else if(!isCrouching && availableJumps> 0 && multipleJumps)
            {
                // Increase the y velocity by the amount of "jumpForce", keep x velocity the same
                rb.velocity = Vector2.up * jumpForce;
                // Keep minus the number of availableJumps while he do the Multiple Jumps
                availableJumps--;
                // Add Jumping animation to the character
                animator.SetBool("Jumping", true);
                Debug.Log("Multiple Jump");
            }
            #endregion
        }  
    }
    // This section will take care of the Low Jump
    void lowJump() {
        // "Lower Jump" or "Jump Cut" Mechanics 
        // if the character is on midair and we released the Jump button, reduce the velocity of y axis
        // Decrease y velocity by the amount of "jumpForce", keep x velocity the same
        rb.velocity = Vector2.up * jumpForce * lowJumpForceModifier;
        // Add Jumping animation to the character
        animator.SetBool("Jumping", true); 
    }
    #endregion
    
    // FixedUpdate will apply the input to the game character regardless of the speed of the game
    void FixedUpdate() {
        GroundCheck();
        Flip(horizontalValue);
        Move(horizontalValue, isRunning, isCrouching);
        // Get the current value of Y velocity in order to add jump animation base on the velocity
        animator.SetFloat("YVelocity", rb.velocity.y);
        
    }

    void Move(float direction, bool runFlag, bool crouchFlag) {
        #region Crouching Mechanics 
        // if the character is standing on the ground
        if(isGrounded==true) {
            // if the character is not crouching,
            if(!crouchFlag)
            {
                // Check if the character is underneath a surface
                if(Physics2D.OverlapCircle(ceilingCheckCollider.position, ceilingCheckRadius, groundLayer2))
                {
                    // If yes, switch to crouching mode
                    crouchFlag = true;
                }    
            }
            // If the character is crouching, disable the headCollider. 
            // If not, reactive it
            headCollider.enabled = !crouchFlag;
        }
        // Add the crouching animation to the character
        animator.SetBool("Crouch", crouchFlag);
        #endregion
     
        #region Walking and Running Mechanics 
        // Push the character to the left or right depending on the input
        // Character's normal speed 
        float walk=direction * runSpeed * Time.fixedDeltaTime * 100;

        // If the character want to run and he is not crouching, increase the walking speed
        if(runFlag==true && crouchFlag==false) walk *=runSpeedModifier;
        // If the character is crouching, decrease the walking speed 
        if(crouchFlag==true) walk *=crouchSpeedModifier;

        rb.velocity=new Vector2(walk, rb.velocity.y); //Change x velocity = "walk", keep y velocity the same
        
        // Adding the Running Animation to the Character
        animator.SetFloat("XVelocity", Mathf.Abs(rb.velocity.x));
        #endregion 
    }

    // Rotate the character base on the moving inputs
    void Flip(float direction) {

        // If the player is looking to right and want to turn left (clicked left)
        if (isFacingRight && direction < 0) {
            transform.localScale=new Vector3(-1, 1, 1);
            isFacingRight=false;
        }

        // If the player is looking to left and want to turn right (clicked right)
        if ( !isFacingRight && direction > 0) {
            transform.localScale=new Vector3(1, 1, 1);
            isFacingRight=true;
        }
    }
}

I would start with something like that我会从这样的事情开始

void GroundCheck(){
    [...]
    if(!wasGrounded)
    {            
        availableJumps = totalJumps; 
        multipleJumps=false;
        if(Time.time - _lastJumpButtonTime < 0.1f){
            Jump();
        }
    }    
    [...]
}

   



void Jump(){
    _lastJumpButtonTime = Time.time;
    [...]
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM