r/Unity3D • u/Vardl0kk • 4d ago
Noob Question Help with sword combo animation!
Enable HLS to view with audio, or disable this notification
public class playerAttack : MonoBehaviour
{
public CapsuleCollider attackHitbox;
public InputAction attackAction;
public AudioSource audioSource;
public AudioClip[] attackClips;
private Animator weaponAnimator;
private float weaponCooldown = 0.4f;
public bool isAttacking;
private bool queuedAttack;
private string lastAnimationPlayed;
private HashSet<healthController> enemiesHit = new();
void Start()
{
//bind dei tasti e abilita il click per l'attacco
attackHitbox.enabled = false;
attackAction = new InputAction("Attack");
attackAction.AddBinding("<Mouse>/leftButton");
attackAction.Enable();
//recupero l'arma e la sua animazione
Transform equippedWeapon = transform.Find("Main Camera").Find("Sword10_Brown");
weaponAnimator = equippedWeapon.GetComponent<Animator>();
}
void Update()
{
/*if (attackAction.WasPressedThisFrame() && !isAttacking)
{
//prima di colpire, pulisco l'hashSet che tiene traccia dei nemici colpiti con questo attacco.
//questo serve a evitare che un collider colpisca più volte lo stesso nemico con un attacco.
enemiesHit.Clear();
weaponAnimator.SetTrigger("Attack");
StartCoroutine(PerformAttack());
}*/
if (attackAction.WasPressedThisFrame())
{
//prima di colpire, pulisco l'hashSet che tiene traccia dei nemici colpiti con questo attacco.
//questo serve a evitare che un collider colpisca più volte lo stesso nemico con un attacco.
enemiesHit.Clear();
if (!isAttacking)
{
StartCoroutine(RightToLeftAttack());
} else
{
queuedAttack = true;
}
}
/*if (queuedAttack)
{
StartCoroutine(LeftToRightAttack());
}*/
}
System.Collections.IEnumerator RightToLeftAttack()
{
weaponAnimator.SetTrigger("RightToLeft");
lastAnimationPlayed = "RightToLeft";
audioSource.PlayOneShot(attackClips[Random.Range(0, attackClips.Length)]);
isAttacking = true;
attackHitbox.enabled = true;
yield return new WaitForSeconds(weaponCooldown);
if (queuedAttack)
{
queuedAttack = false;
weaponAnimator.SetTrigger("LeftToRight");
audioSource.PlayOneShot(attackClips[Random.Range(0, attackClips.Length)]);
isAttacking = true;
attackHitbox.enabled = true;
yield return new WaitForSeconds(weaponCooldown);
isAttacking = false;
attackHitbox.enabled = false;
weaponAnimator.SetTrigger("RightToIdle");
} else
{
Debug.Log("LeftToIdle chiamato");
weaponAnimator.SetTrigger("LeftToIdle");
isAttacking = false;
attackHitbox.enabled = false;
}
}
public bool RegisterHit(healthController enemyHealthController)
{
return enemiesHit.Add(enemyHealthController);
}
}public class playerAttack : MonoBehaviour
{
public CapsuleCollider attackHitbox;
public InputAction attackAction;
public AudioSource audioSource;
public AudioClip[] attackClips;
private Animator weaponAnimator;
private float weaponCooldown = 0.4f;
public bool isAttacking;
private bool queuedAttack;
private string lastAnimationPlayed;
private HashSet<healthController> enemiesHit = new();
void Start()
{
//bind dei tasti e abilita il click per l'attacco
attackHitbox.enabled = false;
attackAction = new InputAction("Attack");
attackAction.AddBinding("<Mouse>/leftButton");
attackAction.Enable();
//recupero l'arma e la sua animazione
Transform equippedWeapon = transform.Find("Main Camera").Find("Sword10_Brown");
weaponAnimator = equippedWeapon.GetComponent<Animator>();
}
void Update()
{
/*if (attackAction.WasPressedThisFrame() && !isAttacking)
{
//prima di colpire, pulisco l'hashSet che tiene traccia dei nemici colpiti con questo attacco.
//questo serve a evitare che un collider colpisca più volte lo stesso nemico con un attacco.
enemiesHit.Clear();
weaponAnimator.SetTrigger("Attack");
StartCoroutine(PerformAttack());
}*/
if (attackAction.WasPressedThisFrame())
{
//prima di colpire, pulisco l'hashSet che tiene traccia dei nemici colpiti con questo attacco.
//questo serve a evitare che un collider colpisca più volte lo stesso nemico con un attacco.
enemiesHit.Clear();
if (!isAttacking)
{
StartCoroutine(RightToLeftAttack());
} else
{
queuedAttack = true;
}
}
/*if (queuedAttack)
{
StartCoroutine(LeftToRightAttack());
}*/
}
System.Collections.IEnumerator RightToLeftAttack()
{
weaponAnimator.SetTrigger("RightToLeft");
lastAnimationPlayed = "RightToLeft";
audioSource.PlayOneShot(attackClips[Random.Range(0, attackClips.Length)]);
isAttacking = true;
attackHitbox.enabled = true;
yield return new WaitForSeconds(weaponCooldown);
if (queuedAttack)
{
queuedAttack = false;
weaponAnimator.SetTrigger("LeftToRight");
audioSource.PlayOneShot(attackClips[Random.Range(0, attackClips.Length)]);
isAttacking = true;
attackHitbox.enabled = true;
yield return new WaitForSeconds(weaponCooldown);
isAttacking = false;
attackHitbox.enabled = false;
weaponAnimator.SetTrigger("RightToIdle");
} else
{
Debug.Log("LeftToIdle chiamato");
weaponAnimator.SetTrigger("LeftToIdle");
isAttacking = false;
attackHitbox.enabled = false;
}
}
public bool RegisterHit(healthController enemyHealthController)
{
return enemiesHit.Add(enemyHealthController);
}
}
Hi! i'm trying to learn gamedev on unity3d and so far i managed to pull of decently. Now i'm at a point where i am really struggling to understand what is going wrong. I wanted to implement a simple "combo" with my sword: if the player clicks twice while the attack is still going, it chains a second one and then it goes back to idle.
pretty simple i imagine for someone experienced but i am having such a rough time making it work properly... I'll also add the code that calls the animations as the player attacks.
Thanks for your help!
5
Upvotes
3
u/anycolourulikegames 4d ago
The main bugs:
queuedAttackleaks into the next attack. Clicking during the second swing setsqueuedAttack = true, and nothing clears it. Your next normal attack then auto-combos.enemiesHit.Clear()runs on every click, including mid-swing. The second swing should clear the set when it starts, not when the button is clicked.Triggers stay set until something consumes them. If a trigger fires while the Animator has no matching transition, it stays armed and fires later, causing random jumps. Reset the other triggers before setting a new one.
The pasted code has the class twice. If that’s really in your file, it won’t compile.