Forum begins after the advertisement:
[Part 3] The Player Character Attacks Twice with one mouse click
Home › Forums › Video Game Tutorial Series › Creating a Metroidvania in Unity › [Part 3] The Player Character Attacks Twice with one mouse click
- This topic has 6 replies, 2 voices, and was last updated 3 months, 3 weeks ago by Adhiraj Patil.
-
AuthorPosts
-
August 29, 2024 at 6:17 am #15701::
Hello guys, for past few Days I’ve been watching the metroidvania game tutorial and I am trying to replicate exact same steps as shown in the video. Now I have reached the part where I have added attack animation. When I press Mouse 1 for attack the attack animation plays but the Player plays the attack animation twice on one click. I have no Idea why this happens, could it be because of the Time.deltaTime we used.
I am attaching my code and Video link in the discription
View post on imgur.com
<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)] [Header("Dash Settings")] bool attack = false; float timeBetweenAttack, timeSinceAttack; 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(); Attack(); } void GetInputs() { xAxis = Input.GetAxisRaw("Horizontal"); attack = Input.GetMouseButton(0); } 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; } void Attack() { timeSinceAttack += Time.deltaTime; if(attack && timeSinceAttack >= timeBetweenAttack) { timeSinceAttack = 0; anim.SetTrigger("Attacking"); } } 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; } } }</code>
August 29, 2024 at 8:22 pm #15706::Adhiraj, thanks for taking the time to post the video. It’s really helpful.
I suspect the issue lies with your animator transition (i.e. the connecting arrow) from Attack back to Idle. Check that the Exit Time for that is set to 1 or below. If it is higher than 1, your animation will repeat itself.
August 29, 2024 at 8:33 pm #15709::Hey Terence, thank you for replying, I went through the animator and checked the transition from attack to idle and the exit time is set to 1. I am attaching a video for the same. Thanks.
August 29, 2024 at 8:39 pm #15710::Can you put the Animator window on the left, then play the game in the Editor and trigger the attack animation? This will allow you to see any issues with animation flow on the Animator window.
Record a video of this and let me have a look at the Animator window.
August 29, 2024 at 10:23 pm #15714::Hey, Yes, I have attached the video also I noticed that If I hold Mouse 1 the character attacks continuously, with delay offcourse.
Link : https://imgur.com/a/ShRAko0
August 29, 2024 at 10:29 pm #15715::Ah, I found the issue now. Add the highlighted portion to your code below:
void GetInputs() { xAxis = Input.GetAxisRaw("Horizontal"); attack = Input.GetMouseButtonDown(0); }
GetMouseButton()
will detect if you hold down the mouse button (i.e. can fire multiple times), whereasGetMouseButtonDown()
will detect only the first frame where you click the mouse (i.e. only fires once).August 29, 2024 at 10:49 pm #15716 -
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: