Ejemplo n.º 1
0
        public static void GetDividedCornersNonAlloc(this NavMeshPath navMeshPath, NavMeshQueryFilter filter,
                                                     float distanceDivider, float yOffset, List <Vector3> outputPath, Vector3[] pathBuffer)
        {
            int count = navMeshPath.GetCornersNonAlloc(pathBuffer);

            navMeshPath.GetDividedCornersNonAlloc(filter, distanceDivider, yOffset, outputPath, pathBuffer, count);
        }
Ejemplo n.º 2
0
        public void CheckPath()
        {
            if (start == null || end == null)
            {
                return;
            }

            NavMeshPath path = new NavMeshPath();

            NavMesh.CalculatePath(start.position, end.position, NavMesh.AllAreas, path);

            PathClear();

            switch (path.status)
            {
            case NavMeshPathStatus.PathComplete:
            case NavMeshPathStatus.PathPartial:
                var count = path.GetCornersNonAlloc(points);
                SetPaths(count, points);
                break;

            case NavMeshPathStatus.PathInvalid:
                Debug.Log("PathInvalid");
                break;
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Looks for a position to investigate in given direction.
        /// </summary>
        public static bool FindNewThreatPositionInDirection(Vector3 direction, AIController controller, ref AISituation situation, NavMeshAgent agent)
        {
            var corners = new Vector3[32];

            float extra = 0f;

            while (extra < 20f)
            {
                var p = situation.CurrentPosition + direction * (controller.Distances.MinSearch + extra);

                var path = new NavMeshPath();
                agent.CalculatePath(p, path);

                if (path.status != NavMeshPathStatus.PathInvalid)
                {
                    int count = path.GetCornersNonAlloc(corners);

                    if (count > 1)
                    {
                        situation.ThreatGroundPosition = corners[count - 1];
                        return(true);
                    }
                }

                extra += 1f;
            }

            return(false);
        }
Ejemplo n.º 4
0
        private void HandleCharacterNavigation()
        {
            if (NavMesh.CalculatePath(Character.transform.position, Destination.position, NavMesh.AllAreas, _path))
            {
                _lastValidDestination = Destination.position;
            }
            else
            {
                NavMesh.CalculatePath(Character.transform.position, _lastValidDestination, NavMesh.AllAreas, _path);
            }

            AICharacterInputs characterInputs = new AICharacterInputs();

            int cornersCount = _path.GetCornersNonAlloc(_pathCorners);

            if (cornersCount > 1)
            {
                // Build the CharacterInputs struct
                characterInputs.MoveVector = (_pathCorners[1] - Character.transform.position).normalized;

                // Apply inputs to character
                Character.SetInputs(ref characterInputs);
            }
            else
            {
                // Build the CharacterInputs struct
                characterInputs.MoveVector = Vector3.zero;

                // Apply inputs to character
                Character.SetInputs(ref characterInputs);
            }
        }
Ejemplo n.º 5
0
        public static Vector3 GetNavPoint(Vector3 current, Vector3 target, float range, int area, out int count, Vector3[] points)
        {
            Vector3 tgt    = target;
            var     random = MovementDictionary.RandomCount;

            for (var i = 0; i < random; i++)
            {
                path.ClearCorners();
                if (NavMesh.CalculatePath(current, tgt, area, path))
                {
                    if (points != null)
                    {
                        count = path.GetCornersNonAlloc(points);
                    }
                    else
                    {
                        count = 0;
                    }

                    return(tgt);
                }

                var circle = UnityEngine.Random.insideUnitCircle;
                tgt += new Vector3(circle.x, 0, circle.y) * range;
            }

            count = 0;
            return(current);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Sets up the navigation agent to move to the givent position.
        /// </summary>
        private void updatePath()
        {
            AIUtil.Path(ref _path, transform.position, _target);

            _pathLength       = _path.GetCornersNonAlloc(_pathPoints);
            _currentPathIndex = 0;

            if (_pathLength > _pathPoints.Length)
            {
                _pathLength = _pathPoints.Length;
            }

            if (_pathLength > 1)
            {
                var vector   = _pathPoints[1] - _pathPoints[0];
                var distance = vector.magnitude;

                if (distance > 0.3f)
                {
                    updateDirection(vector / distance, true);
                }
            }

            _hasCheckedIfReachable      = false;
            _positionToCheckIfReachable = _target;
        }
Ejemplo n.º 7
0
    static int GetCornersNonAlloc(IntPtr L)
    {
        LuaScriptMgr.CheckArgsCount(L, 2);
        NavMeshPath obj = LuaScriptMgr.GetNetObject <NavMeshPath>(L, 1);

        Vector3[] objs0 = LuaScriptMgr.GetArrayObject <Vector3>(L, 2);
        int       o     = obj.GetCornersNonAlloc(objs0);

        LuaScriptMgr.Push(L, o);
        return(1);
    }
Ejemplo n.º 8
0
        /// <summary>
        /// Sets up the navigation agent to move to the givent position.
        /// </summary>
        private void updatePath()
        {
            AIUtil.Path(ref _path, transform.position, _target);

            _pathLength       = _path.GetCornersNonAlloc(_pathPoints);
            _currentPathIndex = 0;

            if (_pathLength > 1)
            {
                updateDirection((_pathPoints[1] - _pathPoints[0]).normalized, true);
            }
        }
Ejemplo n.º 9
0
    public static float CalculateDistance(this NavMeshPath path, Vector3[] corners, out int cornerCount)
    {
        float distance = 0f;

        cornerCount = path.GetCornersNonAlloc(corners);

        for (int i = 1; i < cornerCount; i++)
        {
            distance += Vector3.Distance(corners[i - 1], corners[i]);
        }

        return(distance);
    }
Ejemplo n.º 10
0
    private IEnumerator Run(float initialProgress)
    {
        var fixedUpdateWait = new WaitForFixedUpdate();

        Vector3[] corner = new Vector3[path.corners.Length];
        path.GetCornersNonAlloc(corner);
        var   length        = getLength(path);
        float progress      = initialProgress;
        float breakProgress = 0;
        bool  searchingPath = false;
        bool  waitingForSun = false;
        var   tempLook      = lookTarget;

        while (progress < length - 1)
        {
            yield return(fixedUpdateWait);

            progress += myAgent.speed * Time.fixedDeltaTime;
            var movement = Vector3.ClampMagnitude(sample(corner, progress) - transform.position, myAgent.speed * Time.fixedDeltaTime * gameTime.PlayTime);
            myAgent.Move(Vector3.ClampMagnitude(movement, length - progress));

            Vector3    direction    = (lookTarget - transform.position).normalized;
            Quaternion lookRotation = Quaternion.LookRotation(direction);
            transform.rotation = Quaternion.RotateTowards(transform.rotation, lookRotation, RotationSpeed);

            if (progress >= RecalcThreshold)
            {
                if (!myAgent.pathPending)
                {
                    if (!searchingPath)
                    {
                        searchingPath = true;
                        breakProgress = progress;
                        StartCoroutine(getPath(player.position));
                    }
                    else if (!waitingForSun)
                    {
                        waitingForSun = true;
                        StartCoroutine(calcSun());
                    }
                    else if (!calculatingSun)
                    {
                        run = StartCoroutine(Run(0));
                        yield break;
                    }
                }
            }
        }

        StartCoroutine(agentFollow());
    }
Ejemplo n.º 11
0
    public void GetPathTowards(Vector3 Destination)
    {
        path = new NavMeshPath();
        path.ClearCorners();
        agent.CalculatePath(GetClosestPointToNavMesh(Destination), path);

        if (path == null || path.status == NavMeshPathStatus.PathInvalid)
        {
            Debug.LogError("No path found.");
            return;
        }

        path.GetCornersNonAlloc(Path);
    }
Ejemplo n.º 12
0
    public static NavMeshPath DeserializeNavPath(SerializedVector3[] sPathCorners)
    {
        NavMeshPath path = new NavMeshPath();

        Vector3[] pathCorners = new Vector3[sPathCorners.Length];

        for (int i = 0; i < pathCorners.Length; i++)
        {
            pathCorners[i] = DeserializeVector3(sPathCorners[i]);
        }

        path.GetCornersNonAlloc(pathCorners);
        return(path);
    }
Ejemplo n.º 13
0
        private void MoveDestination(MoveTarget moveTarget, ActorAI actor)
        {
            float   pas         = this.currentSpeedLevel * RandomSpeedFactor * Time.deltaTime;
            Vector3 destination = Vector3.zero;

            switch (moveTarget)
            {
            case MoveTarget.Item:
                destination = ItemTargetDestination;
                break;

            case MoveTarget.Map:
                destination = MapDestination;
                break;

            case MoveTarget.Opponent:
                destination = OpponentTargetDestination;
                break;

            default:
                break;
            }

            destination.y = FloorYOffset;

            NavMeshPath path = new NavMeshPath();

            NavMesh.CalculatePath(actor.transform.position, destination, NavMesh.AllAreas, path);
            Vector3[] pathpoints;
            if (path.status == NavMeshPathStatus.PathComplete)
            {
                pathpoints = new Vector3[path.corners.Length];
                int nbr = path.GetCornersNonAlloc(pathpoints);
                if (nbr > PathVectorIndex)
                {
                    destination = pathpoints[PathVectorIndex];
                }
            }

            destination.y = FloorYOffset;

            Vector3 nouvellePosition = Vector3.MoveTowards(actor.transform.position, destination, pas);
            Vector3 mouvement        = new Vector3(nouvellePosition.x - actor.transform.position.x, nouvellePosition.y - actor.transform.position.y, nouvellePosition.z - actor.transform.position.z);

            float angle = Mathf.Atan2(mouvement.x, mouvement.z) * Mathf.Rad2Deg;

            actor.transform.position = nouvellePosition;
            actor.transform.rotation = Quaternion.AngleAxis(angle, Vector3.up);
        }
Ejemplo n.º 14
0
        private void OnGUI()
        {
            if (debugInfo)
            {
                var cam = Camera.main;
                if (cam == null)
                {
                    return;
                }

                Vector2 size  = Vector2.zero;
                int     index = 1;

                var agentHasPathContent = new GUIContent("Is Agent Moving:  " + agent.hasPath.ToString());
                size = new GUIStyle(GUI.skin.label).CalcSize(agentHasPathContent);
                GUI.Label(new Rect(5f, 5f + (size.y * index), size.x, size.y), agentHasPathContent);
                index++;

                var isMovingContent = new GUIContent("Has Reached Destination:  " + HasReachedDestination().ToString());
                size = new GUIStyle(GUI.skin.label).CalcSize(isMovingContent);
                GUI.Label(new Rect(5f, 5f + (size.y * index), size.x, size.y), isMovingContent);
                index++;

                var getRemainingDistanceContent = new GUIContent("Remaining Distance:  " + GetDistanceRemaining().ToString());
                size = new GUIStyle(GUI.skin.label).CalcSize(getRemainingDistanceContent);
                GUI.Label(new Rect(5f, 5f + (size.y * index), size.x, size.y), getRemainingDistanceContent);
                index++;

                var agentAccelerationContent = new GUIContent("Acceleration:  " + agent.acceleration.ToString());
                size = new GUIStyle(GUI.skin.label).CalcSize(agentAccelerationContent);
                GUI.Label(new Rect(5f, 5f + (size.y * index), size.x, size.y), agentAccelerationContent);
                index++;

                var speedContent = new GUIContent("Speed:  " + agent.speed.ToString());
                size = new GUIStyle(GUI.skin.label).CalcSize(speedContent);
                GUI.Label(new Rect(5f, 5f + (size.y * index), size.x, size.y), speedContent);
                index++;

                if (path != null)
                {
                    var turnAngleContent = new GUIContent("Number Of Corners:  " + path.GetCornersNonAlloc(path.corners).ToString());
                    size = new GUIStyle(GUI.skin.label).CalcSize(turnAngleContent);
                    GUI.Label(new Rect(5f, 5f + (size.y * index), size.x, size.y), turnAngleContent);
                    index++;
                }
            }
        }
Ejemplo n.º 15
0
        private void HandleCharacterNavigation()
        {
            AICharacterInputs aiCharacterInputs = new AICharacterInputs();

            if ((character.transform.position - destination).magnitude <= 0.2f)
            {
                aiCharacterInputs.MoveVector = Vector3.zero;

                // Apply inputs to character
                character.SetInputs(ref aiCharacterInputs);


                return;
            }

            if (NavMesh.CalculatePath(character.transform.position, destination, NavMesh.AllAreas, _path))
            {
                _lastValidDestination = destination;
            }
            else
            {
                NavMesh.CalculatePath(character.transform.position, _lastValidDestination, NavMesh.AllAreas, _path);
            }

            int cornersCount = _path.GetCornersNonAlloc(_pathCorners); //Calculate path corners

            if (cornersCount >= 1)
            {
                // Build the CharacterInputs struct
                aiCharacterInputs.MoveVector = (_pathCorners[1] - character.transform.position).normalized;

                // Apply inputs to character
                character.SetInputs(ref aiCharacterInputs);
            }
            else
            {
                // Build the CharacterInputs struct
                aiCharacterInputs.MoveVector = Vector3.zero;

                // Apply inputs to character
                character.SetInputs(ref aiCharacterInputs);
            }
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Updates the target situation to approach an enemy that's in cover.
        /// </summary>
        public static void ApproachACovered(AIController controller, ref AISituation situation)
        {
            var path    = new NavMeshPath();
            var corners = new Vector3[16];

            var resultPosition = situation.ThreatGroundPosition;
            var resultDistance = 9999f;

            var coverAngle = Util.AngleOfVector(situation.ThreatCoverForward);

            for (int a = 0; a < 18; a++)
            {
                var angle    = coverAngle - 180f + a * 10;
                var position = situation.ThreatGroundPosition + new Vector3(Mathf.Cos(angle * Mathf.Deg2Rad), 0, Mathf.Sin(angle * Mathf.Deg2Rad)) * controller.Distances.MinEnemy;

                NavMeshHit hit;
                if (NavMesh.SamplePosition(position, out hit, 1.0f, NavMesh.AllAreas) &&
                    AIUtil.IsInSight(controller, hit.position, situation.ThreatStandingTopPosition))
                {
                    NavMesh.CalculatePath(controller.transform.position, hit.position, NavMesh.AllAreas, path);

                    if (path.status == NavMeshPathStatus.PathComplete &&
                        !AIUtil.IsPositionTooCloseToFriends(controller, hit.position))
                    {
                        var dist = 0f;

                        for (int i = 1; i < path.GetCornersNonAlloc(corners); i++)
                        {
                            dist += Vector3.Distance(corners[i - 1], corners[i]);
                        }

                        if (dist < resultDistance)
                        {
                            resultDistance = dist;
                            resultPosition = position;
                        }
                    }
                }
            }

            situation.TargetPosition = resultPosition;
            situation.TargetCover    = null;
        }
Ejemplo n.º 17
0
    private bool ExtendPlayerPath(Vector3 targetPosition)
    {
        Vector3 currentPosition = WorldPositionPath.Last != null ? WorldPositionPath.Last.Value : WorldPosition;
        float   targetDistance  = Vector3.Distance(currentPosition, targetPosition);

        if (WorldPositionPath.Count < minPathNodes || targetDistance >= minPathNodeDistance)
        {
            agent.Warp(currentPosition);
            agent.CalculatePath(targetPosition, path);
            agent.Warp(targetPosition);

            pathCornerCount = path.GetCornersNonAlloc(pathCorners);
            for (int i = 0; i < pathCornerCount; i++)
            {
                WorldPositionPath.AddLast(pathCorners[i]);
            }

            return(true);
        }

        return(false);
    }
Ejemplo n.º 18
0
        private float GetDistance(NavMeshPath path)
        {
            var cornersBuffer = ArrayPool <Vector3> .Shared.Rent(MaxCorners);

            try
            {
                var   cornersCount = path.GetCornersNonAlloc(cornersBuffer);
                float distance     = 0;
                if (cornersCount > 1)
                {
                    for (var cornerIndex = 1; cornerIndex < cornersCount; cornerIndex++)
                    {
                        distance += Vector3.Distance(cornersBuffer[cornerIndex - 1], cornersBuffer[cornerIndex]);
                    }
                }

                return(distance);
            }
            finally
            {
                ArrayPool <Vector3> .Shared.Return(cornersBuffer);
            }
        }
Ejemplo n.º 19
0
    public override void findPath(int moveType, SList <PosData> list, PosData from, PosData target)
    {
        list.clear();

        //有路径
        if (NavMesh.CalculatePath(from.getVector(), target.getVector(), BaseC.constlist.mapMoveType_getMask(moveType), _navMeshPath))
        {
            Vector3[] corners = _corners;
            var       len     = _navMeshPath.GetCornersNonAlloc(corners);

            PosData p;

            if (len > 0)
            {
                //跳过起始点
                for (int i = 1; i < len; i++)
                {
                    p = new PosData();
                    p.setByVector(corners[i]);
                    list.add(p);
                }
            }
        }
    }
Ejemplo n.º 20
0
 void Start()
 {
     path = new NavMeshPath();
     NavMesh.CalculatePath(start.localPosition, goal.localPosition, NavMesh.AllAreas, path);
     path.GetCornersNonAlloc(positions);
 }
Ejemplo n.º 21
0
        private bool isValidCover(Cover cover, Vector3 position, int direction, bool checkPath, bool avoidPivot = true)
        {
            if (cover == _unreachableCover)
            {
                return(false);
            }

            if (_isKeepingCloseTo && Vector3.Distance(position, _keepCloseTo.Position) > _keepCloseTo.Distance)
            {
                return(false);
            }

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

                return(true);
            }

            if (!_hasCachedEnemies)
            {
                _cachedEnemyCount = 0;
                _hasCachedEnemies = true;

                var totalActorCount = AIUtil.FindActors(position, MinDefenselessDistance, _actor);

                if (totalActorCount > 0)
                {
                    var enemyCount = 0;
                    for (int i = 0; i < totalActorCount; i++)
                    {
                        if (AIUtil.Actors[i].Side != _actor.Side)
                        {
                            enemyCount++;
                        }
                    }

                    if (enemyCount > 0)
                    {
                        if (_cachedEnemies == null || _cachedEnemies.Length < enemyCount)
                        {
                            _cachedEnemies = new Actor[enemyCount];
                        }

                        var index = 0;

                        for (int i = 0; i < totalActorCount; i++)
                        {
                            if (AIUtil.Actors[i].Side != _actor.Side)
                            {
                                _cachedEnemies[index++] = AIUtil.Actors[i];
                            }
                        }

                        _cachedEnemyCount = index;
                    }
                }
            }

            for (int i = 0; i < _cachedEnemyCount; i++)
            {
                var enemy = _cachedEnemies[i];

                if (enemy.Side != _actor.Side)
                {
                    var enemyPosition = enemy.transform.position;
                    var distance      = Vector3.Distance(position, enemyPosition);

                    if (distance < AvoidDistance)
                    {
                        return(false);
                    }

                    if (!AIUtil.IsGoodAngle(MaxTallCoverThreatAngle,
                                            MaxLowCoverThreatAngle,
                                            cover,
                                            position,
                                            enemyPosition,
                                            cover.IsTall))
                    {
                        return(false);
                    }
                }
            }

            if (_isPivotThreat)
            {
                var distance = Vector3.Distance(position, _pivotPosition);

                if (_hasMaxPivotDistance && distance > _maxPivotDistance)
                {
                    return(false);
                }

                var aimPosition = position;

                if (AIUtil.IsObstructed(aimPosition + (_actor.StandingTopPosition - transform.position),
                                        _pivotPosition + Vector3.up * 2))
                {
                    return(false);
                }
            }
            else
            {
                var distance = Vector3.Distance(position, _pivotPosition);

                if (_hasMaxPivotDistance && distance > _maxPivotDistance)
                {
                    return(false);
                }

                if (!AIUtil.IsGoodAngle(MaxDefenseAngle,
                                        MaxDefenseAngle,
                                        cover,
                                        _pivotPosition,
                                        position,
                                        cover.IsTall))
                {
                    return(false);
                }
            }

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

            if (checkPath)
            {
                if (NavMesh.CalculatePath(transform.position, position, 1, _path))
                {
                    if (avoidPivot)
                    {
                        var count = _path.GetCornersNonAlloc(_corners);

                        for (int i = 0; i < count; i++)
                        {
                            var a = i == 0 ? transform.position : _corners[i - 1];
                            var b = _corners[i];

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

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

            return(true);
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Updates the target situation to approach an enemy that's not in cover.
        /// </summary>
        public static void ApproachAFree(AIController controller, ref AISituation situation, NavMeshAgent agent, float maxDistance, bool approachStanding)
        {
            situation.TargetCover    = null;
            situation.TargetPosition = situation.ThreatGroundPosition;

            var path = new NavMeshPath();

            agent.CalculatePath(situation.ThreatGroundPosition, path);

            var corners = new Vector3[16];
            var count   = path.GetCornersNonAlloc(corners);

            if (count < 2)
            {
                return;
            }

            var i  = 0;
            var p0 = corners[i];
            var p1 = corners[i + 1];
            var f  = 1f;

            var targetPosition = approachStanding ? situation.ThreatStandingTopPosition : situation.ThreatGroundPosition;

            {
                var distLeft = Vector3.Distance(controller.transform.position, situation.ThreatGroundPosition);

                while (distLeft > maxDistance)
                {
                    var pd   = Vector3.Distance(p0, p1);
                    var left = distLeft - maxDistance;
                    distLeft -= pd;

                    if (pd >= left)
                    {
                        f = left / pd;
                        break;
                    }
                    else
                    {
                        i++;

                        if (i + 1 >= count)
                        {
                            i = 0;
                            break;
                        }
                        else
                        {
                            p0 = corners[i];
                            p1 = corners[i + 1];
                        }
                    }
                }
            }

            while (i + 1 < count)
            {
                var p = p0 + (p1 - p0) * f;

                if (AIUtil.IsInSight(controller, p, targetPosition))
                {
                    situation.TargetPosition = p;
                    break;
                }

                f += 0.2f;

                if (f >= 1f)
                {
                    if (AIUtil.IsInSight(controller, p1, targetPosition))
                    {
                        situation.TargetPosition = p1;
                        break;
                    }

                    f = 0;
                    i++;
                }
            }
        }
Ejemplo n.º 23
0
        /// <summary>
        /// Updates the target situation to take cover. Returns true if a cover was found.
        /// </summary>
        public static bool TakeCover(AIController controller, ref AISituation situation)
        {
            var currentVectorToTarget   = situation.ThreatGroundPosition - situation.CurrentPosition;
            var currentDistanceToTarget = currentVectorToTarget.magnitude;

            Cover   result             = null;
            float   resultPathDistance = 0;
            int     resultDirection    = 0;
            Vector3 resultPosition     = situation.CurrentPosition;

            var path    = new NavMeshPath();
            var corners = new Vector3[32];

            var isAlreadyTooClose = currentDistanceToTarget <= controller.Distances.MinEnemy || currentDistanceToTarget <= controller.Cover.MinCoverToEnemyDistance;

            var covers = new List <CoverItem>();

            foreach (var collider in Physics.OverlapSphere(controller.transform.position, controller.Cover.MaxDistance, 0x1 << 8, QueryTriggerInteraction.Collide))
            {
                if (!collider.isTrigger)
                {
                    continue;
                }

                var cover = CoverSearch.GetCover(collider.gameObject);

                if (cover == null || cover == situation.CurrentCover)
                {
                    continue;
                }

                var item = new CoverItem();
                item.Cover  = cover;
                item.IsTall = cover.IsTall(controller.Motor.CoverSettings.TallThreshold);

                if (item.IsTall)
                {
                    item.Direction = cover.ClosestCornerTo(situation.CurrentPosition, controller.Motor.CoverSettings.CornerAimTriggerDistance, out item.Point);
                }
                else
                {
                    item.Point = cover.ClosestPointTo(situation.CurrentPosition, controller.Motor.CoverSettings.LowSideEnterRadius, 0.3f);
                }

                if (float.IsNaN(item.Point.x) || float.IsNaN(item.Point.z))
                {
                    continue;
                }

                item.Point.y  = cover.Bottom;
                item.Distance = Vector3.Distance(controller.transform.position, item.Point);

                covers.Add(item);
            }

            foreach (var item in covers.OrderBy(o => o.Distance))
            {
                var isTall         = item.IsTall;
                var cover          = item.Cover;
                var point          = item.Point;
                var coverDirection = item.Direction;

                if (!AIUtil.IsGoodAngle(controller, cover, point, situation.ThreatGroundPosition, isTall))
                {
                    continue;
                }

                var distanceToTarget = Vector3.Distance(situation.ThreatGroundPosition, point);

                if (distanceToTarget < controller.Distances.MinEnemy ||
                    distanceToTarget < controller.Cover.MinCoverToEnemyDistance)
                {
                    continue;
                }

                if (situation.CurrentCover != null && Vector3.Distance(situation.CurrentPosition, point) < controller.Cover.MinSwitchDistance)
                {
                    continue;
                }

                if ((controller.Health == null || controller.Health.Health > controller.Fighting.MinHealth))
                {
                    if (isTall)
                    {
                        Vector3 aimPoint;
                        coverDirection = cover.ClosestCornerTo(point, -controller.Motor.CoverSettings.CornerOffset.x, out aimPoint);

                        if (!AIUtil.IsInSight(controller, aimPoint, situation.ThreatStandingTopPosition))
                        {
                            continue;
                        }
                    }
                    else if (!AIUtil.IsInSight(controller, point, situation.ThreatStandingTopPosition))
                    {
                        continue;
                    }
                }

                var distanceToOrigin = Vector3.Distance(situation.CurrentPosition, point);

                if (situation.CurrentCover == null)
                {
                    if (distanceToOrigin > controller.Cover.MaxDistance)
                    {
                        continue;
                    }
                }
                else
                if (distanceToOrigin > controller.Cover.MaxSwitchDistance)
                {
                    continue;
                }

                var areThereFriends = false;

                {
                    var hasChangedPosition = false;

                    Vector3 side;

                    if (Vector3.Dot((point - situation.CurrentPosition).normalized, cover.Right) > 0)
                    {
                        side = cover.Right;
                    }
                    else
                    {
                        side = cover.Left;
                    }

                    do
                    {
                        hasChangedPosition = false;

                        if (AIUtil.IsCoverPositionTooCloseToFriends(cover, controller, point))
                        {
                            var next = point + side * 0.5f;

                            if (cover.IsInFront(next, false))
                            {
                                point = next;
                                hasChangedPosition = true;
                            }
                            else
                            {
                                areThereFriends = true;
                            }
                        }
                    }while (hasChangedPosition);
                }

                if (areThereFriends)
                {
                    continue;
                }

                var isOk = false;

                NavMesh.CalculatePath(situation.CurrentPosition, point, NavMesh.AllAreas, path);

                float pathDistance = 0f;

                var count = path.GetCornersNonAlloc(corners);

                if (count < 2)
                {
                    continue;
                }

                var isTooCloseToEnemy = false;

                for (int i = 1; i < count; i++)
                {
                    pathDistance += Vector3.Distance(corners[i - 1], corners[i]);

                    if (!isAlreadyTooClose)
                    {
                        if (Util.DistanceToSegment(situation.ThreatGroundPosition, corners[i - 1], corners[i]) <= controller.Distances.MinPassing)
                        {
                            isTooCloseToEnemy = true;
                            break;
                        }
                    }
                }

                if (isTooCloseToEnemy)
                {
                    continue;
                }

                if (situation.CurrentCover == null)
                {
                    isOk = result == null || pathDistance < resultPathDistance;
                }
                else if (controller.Health == null || controller.Health.Health > controller.Fighting.MinHealth)
                {
                    isOk = (isAlreadyTooClose || distanceToTarget < currentDistanceToTarget) &&
                           (result == null || pathDistance < resultPathDistance);
                }
                else
                {
                    isOk = distanceToTarget > currentDistanceToTarget && (result == null || pathDistance < resultPathDistance);
                }

                if (isOk)
                {
                    result             = cover;
                    resultPosition     = point;
                    resultPathDistance = pathDistance;
                    resultDirection    = coverDirection;
                    break;
                }
            }

            situation.TargetDirection = resultDirection;

            if (result == null)
            {
                if (situation.IsThreatInCover)
                {
                    ApproachACovered(controller, ref situation);
                }
                else
                {
                    ApproachAFree(controller, ref situation, controller.Agent, controller.Distances.MaxWalkingFight, true);
                }

                return(false);
            }
            else
            {
                situation.IsNewCover     = true;
                situation.TargetCover    = result;
                situation.TargetPosition = resultPosition;

                return(true);
            }
        }
Ejemplo n.º 24
0
    // Attempts to find a nearby place that the target can't see us at.
    // Returns true if one was found; if it was, put the position in the
    // hidingSpot variable.
    bool FindHidingSpot(out Vector3 hidingSpot)
    {
        var distribution = new PoissonDiscSampler(
            searchAreaSize, searchAreaSize, searchCellSize);

        var candidateHidingSpots = new List <Vector3>();

        foreach (var point in distribution.Samples())
        {
            var searchPoint = point;

            // Re-position the point so that the middle of the search area
            // is at (0,0)
            searchPoint.x -= searchAreaSize / 2f;
            searchPoint.y -= searchAreaSize / 2f;

            var searchPointLocalSpace = new Vector3(
                searchPoint.x,
                transform.localPosition.y,
                searchPoint.y
                );

            // Can they see us from here?
            var searchPointWorldSpace =
                transform.TransformPoint(searchPointLocalSpace);

            // Find the nearest point on the navmesh
            NavMeshHit hit;

            bool foundPoint;

            foundPoint = NavMesh.SamplePosition(
                searchPointWorldSpace,
                out hit,
                5,
                NavMesh.AllAreas
                );

            if (foundPoint == false)
            {
                // We can't get here. Disregard as a place to hide.
                continue;
            }

            searchPointWorldSpace = hit.position;

            var canSee =
                visibility.CheckVisibilityToPoint(searchPointWorldSpace);


            if (canSee == false)
            {
                // we can't see the target from this position. return it!
                candidateHidingSpots.Add(searchPointWorldSpace);
            }

            if (visualize)
            {
                Color debugColor = canSee ? Color.red : Color.green;

                Debug.DrawLine(
                    transform.position, searchPointWorldSpace,
                    debugColor, 0.1f);
            }
        }

        if (candidateHidingSpots.Count == 0)
        {
            // We didn't find a hiding spot.

            // Provide a dummy value
            hidingSpot = Vector3.zero;

            // Indicate our failure
            return(false);
        }


        // For each of our candidate points, calculate the length of the
        // path needed to reach it.

        // Build a list of candidate points, matched with the length of the
        // path needed to reach it.
        List <KeyValuePair <Vector3, float> > paths;

        // For each point, calculate the length
        paths = candidateHidingSpots.ConvertAll(
            (Vector3 point) => {
            // Create a new path that reaches this point
            var path = new NavMeshPath();
            agent.CalculatePath(point, path);

            // Store the distance needed for this path
            float distance;

            if (path.status != NavMeshPathStatus.PathComplete)
            {
                // If this path doesn't reach the target, consider it
                // infinitely far away
                distance = Mathf.Infinity;
            }
            else
            {
                // Get up to 32 of the points on this path
                var corners     = new Vector3[32];
                var cornerCount = path.GetCornersNonAlloc(corners);

                // Start with the first point
                Vector3 current = corners[0];

                distance = 0;

                // Figure out the cumulative distance for each point
                for (int c = 1; c < cornerCount; c++)
                {
                    var next  = corners[c];
                    distance += Vector3.Distance(current, next);
                    current   = next;
                }
            }

            // Build the pair of point and distance
            return(new KeyValuePair <Vector3, float>(point, distance));
        });

        // Sort this list based on distance, so that the shortest path is
        // at the front of the list
        paths.Sort((a, b) =>
        {
            return(a.Value.CompareTo(b.Value));
        });

        // Return the point that's the shortest to reach
        hidingSpot = paths[0].Key;
        return(true);
    }
Ejemplo n.º 25
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");
                    }
                }
            }
        }
Ejemplo n.º 26
0
        private void findNewFleePosition(bool isAlreadyTooClose)
        {
            var targetPosition = transform.position;
            var targetDot      = -10f;

            var fromThreat = transform.position - _threatPosition;

            fromThreat.y = 0;
            fromThreat.Normalize();

            FleeZone targetBlock = null;

            foreach (var block in FleeZone.All)
            {
                var position = block.transform.position;
                position.y = block.Bottom;

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

                if (block == _targetBlock)
                {
                    continue;
                }

                var dot = -1f;

                if (NavMesh.CalculatePath(transform.position, position, 1, _path))
                {
                    var count = _path.GetCornersNonAlloc(_corners);

                    if (count < 1)
                    {
                        continue;
                    }

                    if (!isAlreadyTooClose)
                    {
                        var isOk = true;

                        for (int i = 0; i < count; 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)
                            {
                                isOk = false;
                                break;
                            }
                        }

                        if (!isOk)
                        {
                            continue;
                        }
                    }

                    var first = _corners[0];
                    if (count > 1)
                    {
                        first = _corners[1];
                    }

                    var vector = first - transform.position;
                    vector.y = 0;
                    vector.Normalize();

                    dot = Vector3.Dot(vector, fromThreat) * Vector3.Distance(position, transform.position);
                }
                else
                {
                    continue;
                }

                if (dot > targetDot)
                {
                    targetDot      = dot;
                    targetPosition = position + (-block.Width * 0.5f + Random.Range(0f, block.Width)) * block.transform.right +
                                     (-block.Depth * 0.5f + Random.Range(0f, block.Depth)) * block.transform.forward;

                    targetBlock = block;
                }
            }

            _targetBlock    = targetBlock;
            _targetPosition = targetPosition;

            Message("ToSprintTo", targetPosition);
            Message("ToFaceWalkDirection", targetPosition);
        }
Ejemplo n.º 27
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);
        }