[英]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.