- Home /
I only want the attack to register once. I'm sorta new to Unity and any help would be greatly appreciated!
When I attack my enemy the attack registers multiple times, starting at 30 and going up in damage by 10 every time (the attack is only supposed to take 10 health from the enemy). Also, when I hold down my attack button (mouse0), the attack registers infinite times. Like the title says I only want the attack to register once upon button press. My project is 2d btw.
Here's my code:
using System.Collections; using System.Collections.Generic; using UnityEngine;
public class SwordPlayer : MonoBehaviour { private Animator anim;
public bool playerInRange;
public Collider2D Collider2D;
public bool hasSword;
public float attackRange = 1f;
public LayerMask enemyLayers;
public Transform SwordattackPTLeft;
public Transform SwordattackPTRight;
void Start()
{
anim = GetComponent<Animator>();
Collider2D = GetComponent<Collider2D>();
}
void Update()
{
if (Input.GetKey(KeyCode.E) && playerInRange)
{
anim.SetBool("hasSword", true);
hasSword = true;
}
//drop sword
if(Input.GetKey(KeyCode.Q))
{
anim.SetBool("hasSword", false);
}
}
private void FixedUpdate()
{
if(hasSword)
{
SwordAttackLeft();
SwordAttackRight();
}
}
private void OnTriggerEnter2D(Collider2D other)
{
if(other.CompareTag("weapon"))
{
playerInRange = true;
}
}
private void OnTriggerExit2D(Collider2D other)
{
if(other.CompareTag("weapon"))
{
playerInRange = false;
}
}
private void SwordAttackLeft()
{
if (Input.GetButton("Fire1") && hasSword)
{
//enemy detection
Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(SwordattackPTLeft.position, attackRange, enemyLayers);
//damage enemies
foreach(Collider2D enemy in hitEnemies)
{
enemy.GetComponent<healthSystem>().TakeDamage(10);
}
}
}
private void SwordAttackRight()
{
if (Input.GetButton("Fire1") && hasSword)
{
//enemy detection
Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(SwordattackPTRight.position, attackRange, enemyLayers);
//damage enemies
foreach(Collider2D enemy in hitEnemies)
{
enemy.GetComponent<healthSystem>().TakeDamage(10);
}
}
}
void OnDrawGizmosSelected()
{
if(SwordattackPTLeft == null)
return;
if(SwordattackPTRight == null)
return;
Gizmos.DrawWireSphere(SwordattackPTLeft.position, attackRange);
Gizmos.DrawWireSphere(SwordattackPTRight.position, attackRange);
}
}
Answer by BuzzyRoboYT · Feb 08 at 07:43 AM
I dont understand some of your code, it seems like your just calling SwordAttackLeft and SwordAttackRight at the same time.
But for your problem try adding a cooldown timer. only attack if the timer is <= 0 if it detects Input.GetButtonUp("Fire1") then you make the timer reset.
Here is the complete code (I cant test it so let me know if it doesnt work):
using UnityEngine;
public class SwordPlayer : MonoBehaviour
{
private Animator anim;
public bool playerInRange;
public Collider2D Collider2D;
public bool hasSword;
public float attackRange = 1f;
public LayerMask enemyLayers;
public Transform SwordattackPTLeft;
public Transform SwordattackPTRight;
private bool attacked = false;
private float timer = 10f;
void Start()
{
anim = GetComponent<Animator>();
Collider2D = GetComponent<Collider2D>();
}
void Update()
{
if (Input.GetKey(KeyCode.E) && playerInRange)
{
anim.SetBool("hasSword", true);
hasSword = true;
}
//drop sword
if (Input.GetKey(KeyCode.Q))
{
anim.SetBool("hasSword", false);
}
}
private void FixedUpdate()
{
if (hasSword)
{
SwordAttackLeft();
SwordAttackRight();
}
//cooldown timer
timer --;
if(Input.GetButtonUp("Fire1") && attacked)
{
timer = 10;
attacked = false;
}
}
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("weapon"))
{
playerInRange = true;
}
}
private void OnTriggerExit2D(Collider2D other)
{
if (other.CompareTag("weapon"))
{
playerInRange = false;
}
}
private void SwordAttackLeft()
{
if (Input.GetButton("Fire1") && hasSword && timer <= 0)
{
//enemy detection
Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(SwordattackPTLeft.position, attackRange, enemyLayers);
//bool for cooldown
attacked = true;
//damage enemies
foreach (Collider2D enemy in hitEnemies)
{
enemy.GetComponent<healthSystem>().TakeDamage(10);
}
}
}
private void SwordAttackRight()
{
if (Input.GetButton("Fire1") && hasSword && timer <= 0)
{
//enemy detection
Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(SwordattackPTRight.position, attackRange, enemyLayers);
//bool for cooldown
attacked = true;
//damage enemies
foreach (Collider2D enemy in hitEnemies)
{
enemy.GetComponent<healthSystem>().TakeDamage(10);
}
}
}
void OnDrawGizmosSelected()
{
if (SwordattackPTLeft == null)
return;
if (SwordattackPTRight == null)
return;
Gizmos.DrawWireSphere(SwordattackPTLeft.position, attackRange);
Gizmos.DrawWireSphere(SwordattackPTRight.position, attackRange);
}
} `
Thank you for helping me out. However it doesn't seem to work, the same problem is happening :/ I got a bit confused so I started to randomly try things before asking on here, sorry that's why the code is a bit confusing.
I tried to clean up the code a bit and got the attack working.
using UnityEngine;
public class SwordPlayer : MonoBehaviour
{
private Animator anim;
public bool playerInRange;
public Collider2D collider2D;
public bool hasSword;
public float attackRange = 1f;
public LayerMask enemyLayers;
public Transform SwordAttackPoint;
private bool attacked = false;
void Start()
{
anim = GetComponent<Animator>();
collider2D = GetComponent<Collider2D>();
}
void Update()
{
if (Input.GetKey(KeyCode.E) && playerInRange)
{
anim.SetBool("hasSword", true);
hasSword = true;
//Destroy weapon object on floor
}
//drop sword
if (Input.GetKey(KeyCode.Q))
{
anim.SetBool("hasSword", false);
//Instantiate new weapon object on floor
}
}
private void FixedUpdate()
{
if (Input.GetButton("Fire1") && attacked == false && hasSword)
{
SwordAttack();
}
if (Input.GetButtonUp("Fire1") && attacked)
{
attacked = false;
}
}
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("weapon"))
{
playerInRange = true;
}
}
private void OnTriggerExit2D(Collider2D other)
{
if (other.CompareTag("weapon"))
{
playerInRange = false;
}
}
private void SwordAttack()
{
Debug.Log("Attack!");
//enemy detection
Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(SwordAttackPoint.position, attackRange, enemyLayers);
//damage enemies
foreach (Collider2D enemy in hitEnemies)
{
enemy.gameObject.GetComponent<healthSystem>().TakeDamage(10);
}
attacked = true;
}
void OnDrawGizmosSelected()
{
if (SwordAttackPoint == null)
{
return;
}
Gizmos.DrawWireSphere(SwordAttackPoint.position, attackRange);
}
}
Thank you so much! This helped a lot, I've been stuck on this for a while and it made me start to lose interest in the project I'm working on, but this being solved has helped me get back into it. I cannot thank you enough!
Your answer
![](https://koobas.hobune.stream/wayback/20220613052742im_/https://answers.unity.com/themes/thub/images/avi.jpg)