2D Combo Attack

In my game, I have two problems:

  1. When my character attacks while moving, he continues to move while the punch animation plays.
  2. I don’t know where to start with coding a combo attack.

I need it so that my character remains still after pressing the attack button and that I can perform a quick three-punch combo.

Here’s my code.

public float playerSpeed, jumpForce;

	public bool grounded = false;
	private bool attacking;

	public Transform groundedEnd;

	Animator anim;

	void Start(){
		anim = GetComponent<Animator> ();
	}

	// Update is called once per frame
	void Update () {
		PlayerMove ();
		Raycasting ();
		attackInput ();
	}

	void FixedUpdate(){
		handleAttacks ();
		resetValues ();
	}

	//attacking
	private void handleAttacks (){
		if (attacking) {
			anim.SetTrigger ("first_punch");
		}
	}

	//attack inputs
	private void attackInput(){
		if(Input.GetKeyDown(KeyCode.Q)){
			attacking = true;
		}
	}

	//player movement function
	void PlayerMove (){

		anim.SetFloat ("speed", Mathf.Abs(Input.GetAxisRaw("Horizontal")));

		//move right
		if(Input.GetAxisRaw ("Horizontal") > 0){
			transform.Translate(Vector3.right * playerSpeed * Time.deltaTime);
			transform.eulerAngles = new Vector2 (0, 0);

		}

		//move left
		if(Input.GetAxisRaw ("Horizontal") < 0){
			transform.Translate(Vector3.right * playerSpeed * Time.deltaTime);
			transform.eulerAngles = new Vector2 (0, 180);
		}

		//jump
		if(Input.GetKeyDown (KeyCode.Space) && (grounded == true)){
			GetComponent<Rigidbody2D> ().AddForce (Vector2.up * jumpForce);
		}
	}

	//check if player is grounded
	void Raycasting(){
		Debug.DrawLine (this.transform.position, groundedEnd.position, Color.green);
		grounded = Physics2D.Linecast (this.transform.position, groundedEnd.position, 1 << LayerMask.NameToLayer("Ground"));
	}

	private void resetValues(){
		attacking = false;
	}
}

Before explaining in detail:

  1. When my character attacks while moving, he continues to move while the
    punch animation plays.
    In essence, you want to stop your character’s movement right when you attack.
  1. I don’t know where to start with coding a combo attack.

First of all, you will need an int variable, to store the combo. Increasing by one for each attack, and going to 0 when no attack is detected for X seconds. In this way, you will know where in the combo you are, and what to do (simple if check on the variable), probably name it something like comboCounter

Alternatively, you can expand your trigger design:

//attacking
     private void handleAttacks (){
         if (attacking) {
             anim.SetTrigger ("first_punch");
         }
     }//didn't change a line, no need to compare, just highlighting that you will be relying on "anim" variable a lot if you go for combos this way

but it will get messy if you want to have big combos, with many outcomes, because you have a lot of dependency to the animator.

Now, on how to stop movement on above script in detail:

First of all, I do not know how your movement works definitely, but I will assume that movement combines both transform and animation (that anim.SetFloat doesn’t say much alone)

//player movement function
     void PlayerMove (){
if (attacking == true)
     return;

anim.SetFloat ("speed", Mathf.Abs(Input.GetAxisRaw("Horizontal")));

However, there is a risk. You reset your value on fixed update. attacking bool should be true for the duration of the attack (and animation) so I don’t think you should reset the value on FixedUpdate(), otherwise you will have to replace the variable I used, with another “isAttacking” boolean which will be messy. attacking bool should become false only when animation/punch has finished, not right after it has set the values you want (in this case, the Trigger) because in this case, your code could become something like this:

 //attacking
     private void handleAttacks (){
     }
 
     //attack inputs
     private void attackInput(){
         if(Input.GetKeyDown(KeyCode.Q)){
             anim.SetTrigger ("first_punch");
         }
     }

Off-topic: If you are dealing with hitboxes, I would suggest you remake the PlayerMove(), so it works only on FixedUpdate, and move with a rigidbody.(Noting the Jump method/function on PlayerMove(), adding force on Update() isn’t as performant as doing it on FixedUpdate() and I don’t see why not move the rigidbody by changing its position or velocity instead of transform, since physics don’t go well with Transform.translate)

[]

I sincerely hope my answer will be useful, although I did delve into “alternatives” which kinda goes against your current code and I apologize for that, it’s just that in the long-term such code may backfire
but all in all, good luck :slight_smile:

(Don’t hesitate to write more if my answer failed)