Forum begins after the advertisement:


[Part 3] Multiple colliders on Enemy causing multiple hits

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [Part 3] Multiple colliders on Enemy causing multiple hits

Viewing 1 post (of 1 total)
  • Author
    Posts
  • #11765
    Terence
    Keymaster

    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.

Viewing 1 post (of 1 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: