Easiest solution is to create a dictionary with a collider as the key and coroutine as the value
private Coroutine _routine;
private Dictionary _colliders;
----------
In DealDamage, after assigning the routine variable to the coroutine, add it to the dictionary
_routine = StartCoroutine((DamageEverySecond(health, rate)));
_colliders[col] = _routine;
----------
In StopDamage, retrieve the coroutine from the dictionary, stop it, then remove it
Coroutine routine = _colliders[col];
StopCoroutine(routine);
_colliders.Remove(col);
----------
This will allow multiple objects to enter and exit the damage zone and apply damage to each without interruption. I created a small test and it works. Here is my test below
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Filip8429
{
public class DamageOverTime : MonoBehaviour
{
[SerializeField] private float delay = 1f;
[SerializeField] private float damage;
private Coroutine _routine;
private WaitForSeconds _wait;
private Dictionary _colliders;
public float Damage { get => damage; private set => damage = value; }
private void Start()
{
_colliders = new Dictionary();
}
private void OnTriggerEnter(Collider other)
{
Debug.Log($"{other.name} entered the damage zone");
DealDamage(other, delay);
}
private void DealDamage(Collider col, float rate)
{
var health = col.GetComponent();
if (health == null) return;
_wait = new WaitForSeconds(rate);
_routine = StartCoroutine((DamageEverySecond(health, rate)));
Debug.Log($"DamageOverTime Coroutine started on {col.name} ");
_colliders[col] = _routine;
}
private void OnTriggerExit(Collider other)
{
StopDamage(other);
}
protected void StopDamage(Collider col)
{
Coroutine routine = _colliders[col];
StopCoroutine(routine);
_colliders.Remove(col);
Debug.Log($"DamageOverTime Coroutine stopped on {col.name} ");
}
private IEnumerator DamageEverySecond(IChangeHealth health, float rate)
{
while (true)
{
health.RemoveHealth(Damage);
yield return _wait;
}
}
}
}
↧