::There’s been an issue reported with our enemy script, that if there are multiple colliders on the enemy, an attack from the player will deal damage multiple times.
A simple way to disable this is to make it so that each enemy can only take a single instance of damage every frame, like so (additions highlighted in green):
public class Enemy : MonoBehaviour
{
[SerializeField] protected float health;
[SerializeField] protected float recoilLength;
[SerializeField] protected float recoilFactor;
[SerializeField] protected bool isRecoiling = false;
[SerializeField] protected float speed;
[SerializeField] protected float damage;
protected float recoilTimer;
protected Rigidbody2D rb;
protected bool hasTakenDamage = false;
// Start is called before the first frame update
protected virtual void Start()
{
}
protected virtual void Awake()
{
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
protected virtual void Update()
{
hasTakenDamage = false;
if(health <= 0)
{
Destroy(gameObject);
}
if(isRecoiling)
{
if(recoilTimer < recoilLength)
{
recoilTimer += Time.deltaTime;
}
else
{
isRecoiling = false;
recoilTimer = 0;
}
}
}
public virtual void EnemyHit(float _damageDone, Vector2 _hitDirection, float _hitForce)
{
if(hasTakenDamage) return;
health -= _damageDone;
if(!isRecoiling)
{
rb.AddForce(-_hitForce * recoilFactor * _hitDirection);
}
hasTakenDamage = true;
}
protected void OnTriggerStay2D(Collider2D _other)
{
if(_other.CompareTag("Player") && !PlayerController.Instance.pState.invincible)
{
Attack();
}
}
protected virtual void Attack()
{
PlayerController.Instance.TakeDamage(damage);
}
}
What this code introduces is a hasTakenDamage
boolean that gets reset to false
every frame. On any given frame, if OnEnemyHit()
is called and damage is dealt, the boolean gets set to true, and will remain true until the next frame, wherein it will be reset.
hasTakenDamage
is also set to protected
so it can be overriden by child classes.