// Update is called once per frame
    void Update()
    {
        // check required events
        if (((CreateProjectile == null || OnHit == null) && DoShot == null) || CanShoot == null)
        {
            return;
        }
        // if the enemy is gone or its tag changed to something no longer targetable
        if (currentTarget == null || !ValidTags.Contains(currentTarget.tag))
        {
            SetNextTargetIfPossible();
        }

        if (currentTarget != null)
        {
            if (CanShoot(Time.time - timeLastShot, projectilesActive))
            {
                timeLastShot = Time.time;
                if (CreateProjectile != null)
                {
                    GameObject             projectile     = CreateProjectile();
                    ProjectileHookBehavior projectileHook = projectile.AddComponent <ProjectileHookBehavior>();
                    projectileHook.enabled = true;
                    projectileHook.OnHit  += (hitObject, hitCollider) =>
                    {
                        if (IsValidTarget(hitObject, hitCollider))
                        {
                            return(OnHit(projectile, hitObject));
                        }

                        return(false);
                    };
                    projectileHook.OnDestroy += (reason) => projectilesActive--;
                }
                else
                {
                    DoShot();
                }
            }
        }
    }
    private bool IsValidTarget(GameObject hit, Collider2D collision)
    {
        // filter self hits
        if (hit == this)
        {
            return(false);
        }

        // filter ignored colliders
        if (IgnoredColliders.Contains(collision))
        {
            return(false);
        }

        // filter null hits and invalid tags
        if (hit == null || !ValidTags.Contains(hit.tag))
        {
            return(false);
        }

        return(true);
    }