繁体   English   中英

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

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

** 我正在尝试 Unity 2D 平台游戏的双跳机制。 我想要的是当角色完成二段跳并且就在它落地之前,如果我们点击任意跳转按钮,角色仍然会知道这是跳转输入。 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;
        }
    }
}

我会从这样的事情开始

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