using UnityEngine; using System.Collections.Generic; using Fusion; namespace Projectiles { /// /// An area that deals damage over time to any IHitTarget that stays inside it. /// public class DamageArea : NetworkBehaviour { // PRIVATE MEMBERS [SerializeField] private float _damagePerSecond = 20f; [SerializeField] private int _hitsPerSecond = 4; [Networked] private TickTimer _cooldown { get; set; } private HashSet _targets = new(); // NetworkBehaviour INTERFACE public override void FixedUpdateNetwork() { if (_damagePerSecond <= 0f) return; // Remove invalid targets _targets.RemoveWhere(t => t.IsActive == false); if (_cooldown.ExpiredOrNotRunning(Runner) == true) { Fire(); } } // MONOBEHAVIOUR private void OnTriggerEnter(Collider other) { if (HasStateAuthority == false) return; var target = other.GetComponentInParent(); if (target != null) { _targets.Add(target); } } private void OnTriggerExit(Collider other) { if (HasStateAuthority == false) return; var target = other.GetComponentInParent(); if (target != null) { _targets.Remove(target); } } // PRIVATE METHODS private void Fire() { // Restart the hit interval _cooldown = TickTimer.CreateFromSeconds(Runner, 1f / _hitsPerSecond); float damage = _damagePerSecond / _hitsPerSecond; foreach (var target in _targets) { var targetPosition = (target as MonoBehaviour).transform.position; HitData hitData = new HitData(); hitData.Action = EHitAction.Damage; hitData.Amount = damage; hitData.Position = targetPosition; hitData.InstigatorRef = Object.InputAuthority; hitData.Direction = (targetPosition - transform.position).normalized; hitData.Normal = Vector3.up; hitData.Target = target; hitData.HitType = EHitType.Suicide; HitUtility.ProcessHit(ref hitData); } } } }