Forum begins after the advertisement:
[Part 2] Variable jump height not working and dash not transitioning
Home › Forums › Video Game Tutorial Series › Creating a Metroidvania in Unity › [Part 2] Variable jump height not working and dash not transitioning
- This topic is empty.
-
AuthorPosts
-
September 28, 2025 at 6:02 pm #18860::
I have 2 problems, the jump height is not variable and the dash animation doesn’t transition into the others: onece dashed the character remains in that state. here’s the code:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerController : MonoBehaviour { [Header("Horizontal Movement Settings:")] [SerializeField] private float walkSpeed = 1; [Space(5)] [Header("Vertical Movement Settings")] [SerializeField] private float jumpForce = 45f; private float jumpBufferCounter = 0; [SerializeField] private float jumpBufferFrames; private float coyoteTimeCounter = 0; [SerializeField] private float coyoteTime; private int airJumpCounter = 0; [SerializeField] private int maxAirJumps; [Space(5)] [Header("Ground Check Settings:")] [SerializeField] private Transform groundCheckPoint; [SerializeField] private float groundCheckY = 0.2f; [SerializeField] private float groundCheckX = 0.5f; [SerializeField] private LayerMask whatIsGround; [Space(5)] [Header("Dash Settings")] [SerializeField] private float dashSpeed; [SerializeField] private float dashTime; [SerializeField] private float dashCooldown; [SerializeField] GameObject dashEffect; [Space(5)] PlayerStateList pState; private Rigidbody2D rb; private float xAxis; private float gravity; Animator anim; private bool canDash = true; private bool dashed; //creates a singleton of the PlayerController public static PlayerController Instance; private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); } else { Instance = this; } } // Start is called before the first frame update void Start() { pState = GetComponent<PlayerStateList>(); rb = GetComponent<Rigidbody2D>(); anim = GetComponent<Animator>(); gravity = rb.gravityScale; } // Update is called once per frame void Update() { GetInputs(); UpdateJumpVariables(); if (pState.dashing) return; Flip(); Move(); Jump(); StartDash(); } void GetInputs() { xAxis = Input.GetAxisRaw("Horizontal"); } void Flip() { if (xAxis < 0) { transform.localScale = new Vector2(-Mathf.Abs(transform.localScale.x), transform.localScale.y); } else if (xAxis > 0) { transform.localScale = new Vector2(Mathf.Abs(transform.localScale.x), transform.localScale.y); } } private void Move() { rb.velocity = new Vector2(walkSpeed * xAxis, rb.velocity.y); anim.SetBool("Walking", rb.velocity.x != 0 && Grounded()); } void StartDash() { if (Input.GetButtonDown("Dash") && canDash && !dashed) { StartCoroutine(Dash()); dashed = true; } if (Grounded()) { dashed = false; } } IEnumerator Dash() { canDash = false; pState.dashing = true; anim.SetTrigger("Dashing"); rb.gravityScale = 0; rb.velocity = new Vector2(transform.localScale.x * dashSpeed, 0); if (Grounded()) Instantiate(dashEffect, transform); yield return new WaitForSeconds(dashTime); rb.gravityScale = gravity; pState.dashing = false; yield return new WaitForSeconds(dashCooldown); canDash = true; } public bool Grounded() { if (Physics2D.Raycast(groundCheckPoint.position, Vector2.down, groundCheckY, whatIsGround) || Physics2D.Raycast(groundCheckPoint.position + new Vector3(groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround) || Physics2D.Raycast(groundCheckPoint.position + new Vector3(-groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround)) { return true; } else { return false; } } void Jump() { if (Input.GetButtonUp("Jump") && rb.velocity.y > 0) { rb.velocity = new Vector2(rb.velocity.x, 0); pState.jumping = false; } if (!pState.jumping) { if (jumpBufferCounter > 0 && coyoteTimeCounter > 0) { rb.velocity = new Vector3(rb.velocity.x, jumpForce); pState.jumping = true; } else if (!Grounded() && airJumpCounter < maxAirJumps && Input.GetButtonDown("Jump")) { pState.jumping = true; airJumpCounter++; rb.velocity = new Vector3(rb.velocity.x, jumpForce); } } anim.SetBool("Jumping", !Grounded()); } void UpdateJumpVariables() { if (Grounded()) { pState.jumping = false; coyoteTimeCounter = coyoteTime; airJumpCounter = 0; } else { coyoteTimeCounter -= Time.deltaTime; } if (Input.GetButtonDown("Jump")) { jumpBufferCounter = jumpBufferFrames; } else { jumpBufferCounter = jumpBufferCounter - Time.deltaTime * 10; } } }
September 28, 2025 at 10:44 pm #18861::To address your two problems:
-
Variable Jump Height: To implement variable jump height, you need to modify the
Jump()
method. Instead of setting the vertical velocity directly tojumpForce
, you can adjust it based on how long the jump button is held down. Here’s how you can modify the jump logic:void Jump() { if (Input.GetButton("Jump") && rb.velocity.y > 0) // Check if the jump button is held { rb.velocity = new Vector2(rb.velocity.x, jumpForce * Time.deltaTime); // Apply a smaller force while holding the button } if (!pState.jumping) { if (jumpBufferCounter > 0 && coyoteTimeCounter > 0) { rb.velocity = new Vector3(rb.velocity.x, jumpForce); pState.jumping = true; } else if (!Grounded() && airJumpCounter < maxAirJumps && Input.GetButtonDown("Jump")) { pState.jumping = true; airJumpCounter++; rb.velocity = new Vector3(rb.velocity.x, jumpForce); } } anim.SetBool("Jumping", !Grounded()); }
-
Dash Animation Transition: To ensure that the dash animation transitions properly into other animations, you need to manage the
dashed
state more effectively. You should reset thedashed
state only after the dash is complete and not immediately when grounded. You can modify theStartDash()
method as follows:void StartDash() { if (Input.GetButtonDown("Dash") && canDash && !dashed) { StartCoroutine(Dash()); dashed = true; } } IEnumerator Dash() { canDash = false; pState.dashing = true; anim.SetTrigger("Dashing"); rb.gravityScale = 0; rb.velocity = new Vector2(transform.localScale.x * dashSpeed, 0); if (Grounded()) Instantiate(dashEffect, transform); yield return new WaitForSeconds(dashTime); rb.gravityScale = gravity; pState.dashing = false; dashed = false; // Reset dashed state after dash is complete yield return new WaitForSeconds(dashCooldown); canDash = true; }
By implementing these changes, you should achieve variable jump heights and ensure that the dash animation transitions correctly into other animations. If you still encounter issues, please provide more details about the specific behavior you're observing.
-
-
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: