/// <summary> Detects and attack one nearest game objects tagged as "Target" on ability's range value area (include skill hit angle). </summary>
        internal TargetDetectionResult MeleeAttackAtSingleTarget(MeleeCharacterClass meleeClass, IAbility ability)
        {
            List <TargetDetectionResult> result = MeleeAttackInArea(meleeClass, ability);

            result.OrderByDescending(x => x.HitDistance);

            return(result.Any() ? result.First() : TargetDetectionResult.BuildAbilityLogicResult(null, ability, 0f));
        }
        /// <summary> Detects all game objects tagged as "Target" on ability's range value area (include skill hit angle). </summary>
        internal List <TargetDetectionResult> MeleeAttackInArea(MeleeCharacterClass meleeClass, IAbility ability)
        {
            List <TargetDetectionResult> AbilityLogicResultList = new List <TargetDetectionResult>();

            // If ability is type of ranged, return default result and print error in unity's console.
            if (ability.IsRanged)
            {
                Debug.LogError(ErrorMessages.WrongTypeOfAbility);
                AbilityLogicResultList.Add(TargetDetectionResult.BuildAbilityLogicResult(null, ability, 0f));

                return(AbilityLogicResultList);
            }

            // Detect all colliders in "ability.Range" radius value.
            Collider[] detectedTargets = Physics.OverlapSphere(meleeClass.transform.position, ability.Range);

            // If any collider has been detected - proceed.
            if (detectedTargets.Length > 0)
            {
                // For each collider, which has been found - execute operations in the loop.
                foreach (Collider targetCollider in detectedTargets)
                {
                    // Check if collider is makred as Target (if the tag was set on the game object).
                    if (targetCollider.CompareTag("Target"))
                    {
                        float   distanceToTarget = Vector3.Distance(meleeClass.transform.position, targetCollider.transform.position);
                        Vector3 direction        = targetCollider.transform.position - meleeClass.transform.position;
                        float   angleOfTarget    = Vector3.Angle(direction, meleeClass.transform.forward);

                        // Check if current target is in the "Hit angle" of used skill.
                        if (angleOfTarget <= (ability.HitAngle * 0.5f))
                        {
                            AbilityLogicResultList.Add(TargetDetectionResult.BuildAbilityLogicResult(targetCollider.GetComponent <ICharacterClass>(),
                                                                                                     ability,
                                                                                                     ability.BaseDamage,
                                                                                                     distanceToTarget,
                                                                                                     angleOfTarget));
                        }
                    }
                }
            }

            return(AbilityLogicResultList);
        }
    private TargetDetectionResult BuildHitColliderDetectionResult(Collider targetCollider)
    {
        float   distanceToTarget = Vector3.Distance(castingCharacter.transform.position, targetCollider.transform.position);
        Vector3 direction        = targetCollider.transform.position - castingCharacter.transform.position;
        float   angleOfTarget    = Vector3.Angle(direction, castingCharacter.transform.forward);

        TargetDetectionResult targetDetectionResult = TargetDetectionResult.BuildAbilityLogicResult(castedAbility,
                                                                                                    targetCollider,
                                                                                                    distanceToTarget);

        if (targetCollider.GetComponent <ICharacterClass>() != null)
        {
            targetDetectionResult = TargetDetectionResult.BuildAbilityLogicResult(targetCollider.GetComponent <ICharacterClass>(),
                                                                                  castedAbility,
                                                                                  castedAbility.BaseDamage,
                                                                                  distanceToTarget,
                                                                                  angleOfTarget);
        }

        return(targetDetectionResult);
    }