Exemplo n.º 1
0
 /// <summary>
 /// Returns position of the left corner moved away from the cover by given margin.
 /// </summary>
 public Vector3 LeftSide(float margin)
 {
     if (Main == null)
     {
         return(new Vector3(0, 999999, 0));
     }
     else
     {
         return(Main.LeftCorner(Observer.y, margin));
     }
 }
        /// <summary>
        /// Returns an updated situation struct.
        /// </summary>
        public void Update(AIController controller, AISituation previous, bool updateInDetail)
        {
            if (!IsAlerted)
            {
                HasInvestigatedTheLatestAlert = false;
            }
            else if (Threat == null & Vector3.Distance(CurrentPosition, ThreatGroundPosition) < controller.Distances.ThreatInvestigation)
            {
                MarkInvestigated();
            }

            if (HasAnInvestigatedAlert)
            {
                InvestigatedAlertAge += Time.deltaTime;
            }

            // Check grenades
            {
                IsNearGrenade = false;
                float minDist = 1000;

                foreach (var grenade in GrenadeList.All)
                {
                    var vec  = grenade.transform.position - controller.transform.position;
                    var dist = vec.magnitude;

                    if (dist < grenade.ExplosionRadius)
                    {
                        if (!IsNearGrenade || dist < minDist)
                        {
                            minDist                = dist;
                            IsNearGrenade          = true;
                            NearestGrenadePosition = grenade.transform.position;

                            if (Threat == null)
                            {
                                HasInvestigatedTheLatestAlert = false;
                                HasAnInvestigatedAlert        = false;
                                ThreatGroundPosition          = grenade.transform.position;
                            }
                        }
                    }
                }
            }

            // Check friends and enemies.
            if (Threat == null || (!IsAlerted && !IsGettingAlerted))
            {
                var minEnemyInfoTimer = controller.View.EnemySustainTime;

                foreach (var actor in Actors.All)
                {
                    if (actor != controller.Actor)
                    {
                        if (actor.Side != controller.Actor.Side)
                        {
                            if (AIUtil.IsInSight(controller, actor.TopPosition))
                            {
                                IsAlerted = true;
                                ReadEnemyState(actor);
                                break;
                            }
                        }
                        else if (actor.AI != null && actor.AI.IsAlerted)
                        {
                            var vector = actor.transform.position - controller.transform.position;

                            if (vector.magnitude < controller.View.CommunicationDistance)
                            {
                                IsAlerted = true;

                                if (actor.AI.Situation.NoThreatTimer < actor.AI.View.EnemySustainTime &&
                                    minEnemyInfoTimer > actor.AI.Situation.NoThreatTimer)
                                {
                                    TakeEnemyState(actor.AI);
                                }
                            }
                        }
                    }
                }
            }

            // Check friends if they had investigated the same position
            if (IsAlerted && Threat == null && !HasInvestigatedTheLatestAlert)
            {
                foreach (var friend in Actors.All)
                {
                    if (friend != controller.Actor &&
                        friend.Side == controller.Actor.Side &&
                        friend.AI.IsAlerted &&
                        friend.AI.Situation.HasAnInvestigatedAlert &&
                        friend.AI.Situation.InvestigatedAlertAge < 10 &&
                        Vector3.Distance(friend.transform.position, controller.transform.position) < controller.View.CommunicationDistance &&
                        Vector3.Distance(friend.AI.Situation.InvestigatedThreatPosition, ThreatGroundPosition) < controller.Distances.ThreatInvestigation)
                    {
                        MarkInvestigated();
                        break;
                    }
                }
            }


            // Check threats
            if (Threat == null)
            {
                var minDist = 100000f;

                foreach (var alert in Alerts.All)
                {
                    var dist = Vector3.Distance(controller.transform.position, alert.Position);

                    if (dist < alert.Range)
                    {
                        if (dist < minDist)
                        {
                            minDist                       = dist;
                            IsAlerted                     = true;
                            ThreatGroundPosition          = alert.Position;
                            HasAnInvestigatedAlert        = false;
                            HasInvestigatedTheLatestAlert = false;
                        }
                    }
                }
            }

            // React to grenades
            if (IsNoticingGrenade)
            {
                if (GrenadeReaction < float.Epsilon)
                {
                    IsNoticingGrenade = false;
                }
                else
                {
                    GrenadeReaction -= Time.deltaTime;
                    IsNearGrenade    = false;
                }
            }
            else if (IsNearGrenade && !previous.IsNearGrenade)
            {
                GrenadeReaction   = controller.Fighting.GrenadeReactionTime;
                IsNoticingGrenade = true;
                IsNearGrenade     = false;
            }

            if (IsNearGrenade)
            {
                IsAlerted = true;
            }

            // React to being alerted.
            if (IsGettingAlerted)
            {
                if (AlertReaction < float.Epsilon)
                {
                    IsGettingAlerted = false;
                    IsAlerted        = true;
                }
                else
                {
                    AlertReaction -= Time.deltaTime;
                    IsAlerted      = false;
                }
            }
            else if (IsAlerted && !previous.IsAlerted)
            {
                AlertReaction    = controller.Fighting.ReactionTime;
                IsGettingAlerted = true;
                IsAlerted        = false;
            }

            if (previous.TargetCover != null &&
                (controller.Motor.LeftCover == previous.TargetCover || controller.Motor.RightCover == previous.TargetCover || controller.Motor.Cover == previous.TargetCover))
            {
                CurrentCover = previous.TargetCover;
            }
            else
            {
                CurrentCover = controller.Motor.Cover;
            }

            CurrentPosition = controller.transform.position;
            IsGunReady      = controller.Motor.IsGunReady && controller.Motor.Gun.Clip >= controller.Motor.Gun.ClipSize * controller.Fighting.ReloadFraction;

            if (controller.Health != null && Threat != null && Threat.IsAttacking)
            {
                IsRetreating = IsAlerted && controller.Health.Health <= controller.Fighting.MinHealth;
            }
            else
            {
                IsRetreating = false;
            }

            if (IsAlerted)
            {
                var couldSeeTheEnemy = CanSeeTheThreat;
                CanSeeTheThreat = false;

                if (Threat != null)
                {
                    if (couldSeeTheEnemy || updateInDetail)
                    {
                        CanSeeTheThreat = AIUtil.IsInSight(controller, Threat.TopPosition);
                    }

                    if (CanSeeTheThreat)
                    {
                        ReadEnemyState(Threat);
                    }
                    else
                    {
                        NoThreatTimer += Time.deltaTime;

                        if (updateInDetail)
                        {
                            // Check friends and enemies.
                            foreach (var friend in Actors.All)
                            {
                                if (friend != controller.Actor &&
                                    friend.Side == controller.Actor.Side &&
                                    friend.AI != null &&
                                    friend.AI.IsAlerted &&
                                    friend.AI.Situation.CanSeeTheThreat &&
                                    friend.AI.Situation.Threat == Threat)
                                {
                                    var vector = friend.transform.position - controller.transform.position;

                                    if (vector.magnitude < controller.View.CommunicationDistance)
                                    {
                                        TakeEnemyState(friend.AI);
                                    }
                                }
                            }
                        }
                    }
                }

                if (TargetCover != null && updateInDetail)
                {
                    var distanceToThreat = Vector3.Distance(TargetPosition, ThreatGroundPosition);

                    IsTargetCoverGood = distanceToThreat >= controller.Distances.MinEnemy &&
                                        distanceToThreat >= controller.Cover.MinCoverToEnemyDistance &&
                                        AIUtil.IsGoodAngle(controller,
                                                           TargetCover,
                                                           TargetPosition,
                                                           ThreatGroundPosition,
                                                           TargetCover.IsTall(controller.Motor.CoverSettings.TallThreshold)) &&
                                        !AIUtil.IsCoverPositionTooCloseToFriends(TargetCover, controller, TargetPosition);
                }

                if (updateInDetail)
                {
                    if (TargetCover != null && TargetCover.IsTall(controller.Motor.CoverSettings.TallThreshold))
                    {
                        Vector3 aimPoint;

                        if (TargetDirection < 0)
                        {
                            aimPoint = TargetCover.LeftCorner(0, controller.Motor.CoverSettings.CornerOffset.x);
                        }
                        else
                        {
                            aimPoint = TargetCover.RightCorner(0, controller.Motor.CoverSettings.CornerOffset.x);
                        }

                        CanSeeFromTargetPosition = AIUtil.IsInSight(controller, aimPoint, ThreatStandingTopPosition);
                    }
                    else
                    {
                        CanSeeFromTargetPosition = AIUtil.IsInSight(controller, TargetPosition, ThreatStandingTopPosition);
                    }
                }
            }
            else
            {
                if (TargetCover != null && updateInDetail)
                {
                    IsTargetCoverGood = !AIUtil.IsCoverPositionTooCloseToFriends(TargetCover, controller, TargetPosition);
                }

                CanSeeFromTargetPosition = true;
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Told by the brains to investigate a position.
        /// </summary>
        /// <param name="position"></param>
        public void ToInvestigatePosition(Vector3 position)
        {
            _isInvestigating = true;

            _position = position;
            _cover    = null;
            var minDistance = 0f;

            for (int i = 0; i < Physics.OverlapSphereNonAlloc(position, CoverSearchDistance, _colliders, 0x1 << 8, QueryTriggerInteraction.Collide); i++)
            {
                var cover = CoverSearch.GetCover(_colliders[i].gameObject);

                if (cover != null)
                {
                    var point    = cover.ClosestPointTo(position, 0.3f, 0.3f);
                    var distance = Vector3.Distance(position, point);

                    if (distance < minDistance || _cover == null)
                    {
                        _cover      = cover;
                        _position   = point;
                        minDistance = distance;
                    }
                }
            }

            _verifyDistance = Util.GetViewDistance(_position, VerifyDistance, true);

            if (_cover == null)
            {
                _hasReachedCoverLine = false;

                if (isActiveAndEnabled)
                {
                    Message("ToWalkTo", position);
                    Message("OnInvestigationStart");
                }
            }
            else
            {
                var vector = _position - transform.position;
                _hasReachedCoverLine = Vector3.Dot(_cover.Forward, vector) > 0;

                if (_hasReachedCoverLine)
                {
                    if (isActiveAndEnabled)
                    {
                        Message("ToWalkTo", _position);
                        Message("OnInvestigationStart");
                    }
                }
                else
                {
                    var left  = _cover.LeftCorner(_cover.Bottom, CoverOffset) - _cover.Forward * 1.0f;
                    var right = _cover.RightCorner(_cover.Bottom, CoverOffset) - _cover.Forward * 1.0f;

                    AIUtil.Path(ref _path, transform.position, left);
                    var leftLength = 0f;

                    if (_path.status == NavMeshPathStatus.PathInvalid)
                    {
                        leftLength = 999999f;
                    }
                    else
                    {
                        for (int i = 1; i < _path.GetCornersNonAlloc(_corners); i++)
                        {
                            leftLength += Vector3.Distance(_corners[i], _corners[i - 1]);
                        }
                    }

                    AIUtil.Path(ref _path, transform.position, right);
                    var rightLength = 0f;

                    if (_path.status == NavMeshPathStatus.PathInvalid)
                    {
                        rightLength = 999999f;
                    }
                    else
                    {
                        for (int i = 1; i < _path.GetCornersNonAlloc(_corners); i++)
                        {
                            rightLength += Vector3.Distance(_corners[i], _corners[i - 1]);
                        }
                    }

                    if (leftLength < rightLength)
                    {
                        _approachPosition = left;
                    }
                    else
                    {
                        _approachPosition = right;
                    }

                    var distance = Vector3.Distance(_approachPosition, _position);

                    if (distance + VerifyRadius > _verifyDistance)
                    {
                        _approachPosition = _position + Vector3.Normalize(_approachPosition - _position) * (_verifyDistance + VerifyRadius - 0.1f);
                    }

                    if (isActiveAndEnabled)
                    {
                        Message("ToWalkTo", _approachPosition);
                        Message("OnInvestigationStart");
                    }
                }
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Returns an updated situation struct.
        /// </summary>
        public void Update(AIController controller, AISituation previous, bool updateInDetail)
        {
            if (!IsAlerted)
            {
                HasInvestigatedTheLatestAlert = false;
            }
            else if (!HasInvestigatedTheLatestAlert && Vector3.Distance(CurrentPosition, InvestigationPosition) < controller.Distances.ThreatInvestigation)
            {
                MarkInvestigated();
            }

            if (HasAnInvestigatedAlert)
            {
                InvestigatedAlertAge += Time.deltaTime;
            }

            if (IsIrritated)
            {
                if (IrritationTime > controller.Fighting.Irritation)
                {
                    IrritationTime = 0;
                    IsIrritated    = false;
                }
                else
                {
                    IrritationTime += Time.deltaTime;
                }
            }
            else
            {
                IrritationTime = 0;
            }

            // Check grenades
            {
                IsNearGrenade = false;
                float minDist = 1000;

                foreach (var grenade in GrenadeList.All)
                {
                    var vec  = grenade.transform.position - controller.transform.position;
                    var dist = vec.magnitude;

                    if (dist < grenade.ExplosionRadius)
                    {
                        if (!IsNearGrenade || dist < minDist)
                        {
                            minDist                = dist;
                            IsNearGrenade          = true;
                            NearestGrenadePosition = grenade.transform.position;

                            if (Threat == null)
                            {
                                HasInvestigatedTheLatestAlert = false;
                                HasAnInvestigatedAlert        = false;
                                IsThreatPositionANewAlert     = true;
                                SetThreatPosition(grenade.transform.position, true);
                            }
                        }
                    }
                }
            }

            // Check friends and enemies.
            if (Threat == null || (!IsAlerted && !IsGettingAlerted))
            {
                foreach (var actor in Actors.All)
                {
                    if (actor != controller.Actor)
                    {
                        if (actor.Side != controller.Actor.Side)
                        {
                            if (AIUtil.IsInSight(controller, actor.TopPosition))
                            {
                                IsAlerted = true;
                                ReadEnemyState(actor);
                                break;
                            }
                        }
                        else if (actor.AI != null && actor.AI.IsAlerted)
                        {
                            var vector = actor.transform.position - controller.transform.position;

                            if (vector.magnitude < controller.View.CommunicationDistance)
                            {
                                IsAlerted = true;

                                if (actor.AI.State != AIState.investigate)
                                {
                                    if (actor.AI.Situation.Threat != null && actor.AI.Situation.HasBetterThreatInfo(actor.AI, ref this))
                                    {
                                        TakeEnemyState(actor.AI);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // Check friends if they had investigated the same position
            if (IsAlerted && !HasInvestigatedTheLatestAlert)
            {
                foreach (var friend in Actors.All)
                {
                    if (friend != controller.Actor &&
                        friend.Side == controller.Actor.Side &&
                        friend.AI != null &&
                        friend.AI.IsAlerted &&
                        friend.AI.Situation.HasAnInvestigatedAlert &&
                        friend.AI.Situation.InvestigatedAlertAge < 4 &&
                        Vector3.Distance(friend.transform.position, controller.transform.position) < controller.View.CommunicationDistance &&
                        Vector3.Distance(friend.AI.Situation.InvestigatedThreatPosition, InvestigationPosition) < controller.Distances.ThreatInvestigation)
                    {
                        MarkInvestigated();
                        break;
                    }
                }
            }

            var isCheckingAThreatInCover = Threat != null && IsThreatInCover && !CanSeeTheThreat;

            // Check threats
            if (Threat == null || CanSeeThatNoThreatAtLastPosition || isCheckingAThreatInCover)
            {
                var minDist = 100000f;

                foreach (var alert in Alerts.All)
                {
                    bool  isOk;
                    Actor newThreat = null;

                    if (Threat != null)
                    {
                        if (alert.Actor == null)
                        {
                            isOk = NoThreatVisibilityTime > 6;
                        }
                        else if (alert.Actor.Side != controller.Actor.Side)
                        {
                            isOk      = true;
                            newThreat = alert.Actor;
                        }
                        else if (alert.Actor.AI != null)
                        {
                            isOk = NoThreatVisibilityTime > 2 && alert.Actor.AI.Situation.NoThreatVisibilityTime < 1;
                        }
                        else
                        {
                            isOk = NoThreatVisibilityTime > 6;
                        }
                    }
                    else
                    {
                        isOk = true;
                    }

                    if (isOk)
                    {
                        var dist = Vector3.Distance(controller.transform.position, alert.Position);

                        if (dist < alert.Range)
                        {
                            if (dist < minDist)
                            {
                                minDist   = dist;
                                IsAlerted = true;

                                HasAnInvestigatedAlert        = false;
                                HasInvestigatedTheLatestAlert = false;

                                if (newThreat != null)
                                {
                                    ReadEnemyState(newThreat);
                                }
                                else
                                {
                                    IsThreatPositionANewAlert = true;
                                    SetThreatPosition(alert.Position, true);
                                }
                            }
                        }
                    }
                }
            }

            // React to grenades
            if (IsNoticingGrenade)
            {
                if (GrenadeReaction < float.Epsilon)
                {
                    IsNoticingGrenade = false;
                }
                else
                {
                    GrenadeReaction -= Time.deltaTime;
                    IsNearGrenade    = false;
                }
            }
            else if (IsNearGrenade && !previous.IsNearGrenade)
            {
                GrenadeReaction   = controller.Fighting.GrenadeReactionTime;
                IsNoticingGrenade = true;
                IsNearGrenade     = false;
            }

            if (IsNearGrenade)
            {
                IsAlerted = true;
            }

            // React to being alerted.
            if (IsGettingAlerted)
            {
                if (AlertReaction < float.Epsilon)
                {
                    IsGettingAlerted = false;
                    IsAlerted        = true;
                }
                else
                {
                    AlertReaction -= Time.deltaTime;
                    IsAlerted      = false;
                }
            }
            else if (IsAlerted && !previous.IsAlerted)
            {
                AlertReaction    = controller.Fighting.ReactionTime;
                IsGettingAlerted = true;
                IsAlerted        = false;
            }

            if (previous.TargetCover != null &&
                (controller.Motor.LeftCover == previous.TargetCover || controller.Motor.RightCover == previous.TargetCover || controller.Motor.Cover == previous.TargetCover))
            {
                CurrentCover = previous.TargetCover;
            }
            else
            {
                CurrentCover = controller.Motor.Cover;
            }

            CurrentPosition = controller.transform.position;
            IsGunReady      = controller.Motor.IsGunReady && controller.Motor.Gun.Clip >= controller.Motor.Gun.ClipSize * controller.Fighting.ReloadFraction;

            if (Threat == null || Threat.IsAggressive)
            {
                WouldLikeToRetreat = controller.Health.Health <= controller.Fighting.MinHealth;
            }
            else
            {
                WouldLikeToRetreat = false;
            }

            if (IsAlerted)
            {
                var couldSeeTheEnemy = CanSeeTheThreat;
                CanSeeTheThreat = false;

                if (Threat != null)
                {
                    var noPatience = NoThreatVisibilityTime > controller.Fighting.Patience;

                    if (couldSeeTheEnemy || updateInDetail)
                    {
                        CanSeeTheThreat = AIUtil.IsInSight(controller, Threat.TopPosition);
                    }

                    if (CanSeeTheThreat)
                    {
                        ReadEnemyState(Threat);

                        if (!couldSeeTheEnemy && noPatience)
                        {
                            IsIrritated = true;
                        }
                    }
                    else
                    {
                        if (noPatience || (NoThreatVisibilityTime > 2 && (!IsThreatInCover || Vector3.Dot(ThreatCoverForward, ThreatGroundPosition - CurrentPosition) > 0)))
                        {
                            if (!IsThreatInCover ||
                                noPatience ||
                                Vector3.Distance(CurrentPosition, ThreatGroundPosition) < controller.Distances.ThreatInvestigation ||
                                AIUtil.IsInSight(controller, (ThreatGroundPosition + ThreatTopPosition) * 0.5f))
                            {
                                CanSeeThatNoThreatAtLastPosition = true;
                            }
                        }

                        NoThreatVisibilityTime += Time.deltaTime;

                        if (updateInDetail)
                        {
                            // Check friends.
                            foreach (var friend in Actors.All)
                            {
                                if (friend != controller.Actor &&
                                    friend.Side == controller.Actor.Side &&
                                    friend.AI != null &&
                                    friend.AI.IsAlerted &&
                                    friend.AI.State != AIState.investigate &&
                                    friend.AI.Situation.Threat == Threat &&
                                    friend.AI.Situation.HasBetterThreatInfo(friend.AI, ref this))
                                {
                                    var vector = friend.transform.position - controller.transform.position;

                                    if (vector.magnitude < controller.View.CommunicationDistance)
                                    {
                                        TakeEnemyState(friend.AI);
                                    }
                                }
                            }
                        }
                    }
                }

                if (TargetCover != null && updateInDetail)
                {
                    var distanceToThreat = Vector3.Distance(TargetPosition, ThreatGroundPosition);

                    IsTargetCoverGood = distanceToThreat >= controller.Distances.MinEnemy &&
                                        distanceToThreat >= controller.Cover.MinCoverToEnemyDistance &&
                                        AIUtil.IsGoodAngle(controller,
                                                           TargetCover,
                                                           TargetPosition,
                                                           ThreatGroundPosition,
                                                           TargetCover.IsTall) &&
                                        !AIUtil.IsCoverPositionTooCloseToFriends(TargetCover, controller, TargetPosition);
                }

                if (updateInDetail)
                {
                    if (IsThreatInCover)
                    {
                        if (CurrentCover != null && CurrentCover.IsTall)
                        {
                            var aimPoint = Vector3.zero;
                            var isGood   = true;

                            if (TargetDirection < 0)
                            {
                                isGood = CurrentCover.IsLeft(Util.AngleOfVector(ThreatStandingTopPosition - CurrentCover.LeftCorner(0)), controller.Motor.CoverSettings.Angles.LeftCorner, false);

                                if (isGood)
                                {
                                    aimPoint = CurrentCover.LeftCorner(0, controller.Motor.CoverSettings.CornerOffset.x);
                                }
                            }
                            else
                            {
                                isGood = CurrentCover.IsRight(Util.AngleOfVector(ThreatStandingTopPosition - CurrentCover.RightCorner(0)), controller.Motor.CoverSettings.Angles.LeftCorner, false);

                                if (isGood)
                                {
                                    aimPoint = CurrentCover.RightCorner(0, controller.Motor.CoverSettings.CornerOffset.x);
                                }
                            }

                            CanSeeFromCurrentPosition = AIUtil.IsInSight(controller, aimPoint, ThreatStandingTopPosition);
                        }
                        else
                        {
                            CanSeeFromCurrentPosition = AIUtil.IsInSight(controller, CurrentPosition, ThreatStandingTopPosition);
                        }
                    }
                    else
                    {
                        CanSeeFromCurrentPosition = CanSeeTheThreat;
                    }
                }
            }
            else
            {
                if (TargetCover != null && updateInDetail)
                {
                    IsTargetCoverGood = !AIUtil.IsCoverPositionTooCloseToFriends(TargetCover, controller, TargetPosition);
                }
            }
        }
Exemplo n.º 5
0
        private bool isValidCover(Cover cover, Vector3 position, int direction, bool checkPath)
        {
            if (!_hasThreat)
            {
                return(true);
            }

            if (Vector3.Distance(position, _threatPosition) < AvoidDistance)
            {
                return(false);
            }

            if (!AIUtil.IsGoodAngle(MaxTallCoverAngle,
                                    MaxLowCoverAngle,
                                    cover,
                                    position,
                                    _threatPosition,
                                    cover.IsTall))
            {
                return(false);
            }

            if (!AIUtil.IsCoverPositionFree(cover, position, 1, _actor))
            {
                return(false);
            }

            var aimPosition = position;

            if (cover.IsTall)
            {
                var angle = Util.AngleOfVector(_threatPosition - position);

                if (direction > 0)
                {
                    if (!cover.IsFrontField(angle, _motor.CoverSettings.Angles.TallRightCornerFront))
                    {
                        return(false);
                    }

                    if (!cover.IsRight(angle, _motor.CoverSettings.Angles.RightCorner, false))
                    {
                        return(false);
                    }

                    aimPosition = cover.RightCorner(cover.Bottom, _motor.CoverSettings.CornerOffset.x);
                }
                else if (direction < 0)
                {
                    if (!cover.IsFrontField(angle, _motor.CoverSettings.Angles.TallLeftCornerFront))
                    {
                        return(false);
                    }

                    if (!cover.IsLeft(angle, _motor.CoverSettings.Angles.LeftCorner, false))
                    {
                        return(false);
                    }

                    aimPosition = cover.LeftCorner(cover.Bottom, _motor.CoverSettings.CornerOffset.x);
                }
            }

            if (AIUtil.IsObstructed(aimPosition + (_actor.StandingTopPosition - transform.position),
                                    _threatPosition + Vector3.up * 2,
                                    100))
            {
                return(false);
            }

            if (checkPath)
            {
                if (Vector3.Distance(transform.position, _threatPosition) > AvoidDistance)
                {
                    if (NavMesh.CalculatePath(transform.position, position, 1, _path))
                    {
                        for (int i = 0; i < _path.GetCornersNonAlloc(_corners); i++)
                        {
                            var a = i == 0 ? transform.position : _corners[i - 1];
                            var b = _corners[i];

                            var closest = Util.FindClosestToPath(a, b, _threatPosition);

                            if (Vector3.Distance(closest, _threatPosition) < AvoidDistance)
                            {
                                return(false);
                            }
                        }
                    }
                    else
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }