Example #1
0
        private void startSearch()
        {
            _isSearching = true;
            _hasPoint    = false;

            _blocks.Clear();

            ToClearSearchHistory();

            for (int i = 0; i < _investigatedBlocks.Count; i++)
            {
                _blockCache.Give(_investigatedBlocks[i]);
            }

            _investigatedBlocks.Clear();

            _hasPreviousPoint = false;
            _points.Clear();

            GlobalSearchCache.GeneratedPoints.WriteTo(_points);

            for (int i = 0; i < GlobalSearchCache.GeneratedBlocks.Count; i++)
            {
                var block = _blockCache.Take();
                GlobalSearchCache.GeneratedBlocks[i].WriteTo(ref block);

                _blocks.Add(block);
            }
        }
Example #2
0
        /// <summary>
        /// Rebuilds the search point database.
        /// </summary>
        public static void Rebuild()
        {
            const float searchRadius = 1000;

            _isGenerating = true;
            _currentMergedGeneratedBlockId = 0;
            _timeAtGenerationStart         = Time.timeSinceLevelLoad;

            for (int i = 0; i < _blocks.Count; i++)
            {
                _blockCache.Give(_blocks[i]);
            }

            _blocks.Clear();
            _usedCovers.Clear();
            _points.Clear();

            _coverCache.Items.Clear();
            _coverCache.Reset(Vector3.zero, searchRadius, false);

            for (int i = 0; i < _coverCache.Items.Count; i++)
            {
                var item = _coverCache.Items[i];

                if (_usedCovers.Contains(item.Cover))
                {
                    continue;
                }

                var cover    = item.Cover;
                var starting = item.Cover;

                while (cover.LeftAdjacent != null && !_usedCovers.Contains(cover.LeftAdjacent))
                {
                    if (cover.LeftAdjacent == starting)
                    {
                        break;
                    }

                    cover = cover.LeftAdjacent;
                }

                var index = -1;

                while (cover != null)
                {
                    _usedCovers.Add(cover);

                    var left   = cover.LeftCorner(cover.Bottom) - cover.Forward * 0.25f;
                    var right  = cover.RightCorner(cover.Bottom) - cover.Forward * 0.25f;
                    var vector = right - left;
                    var length = vector.magnitude;

                    var leftApproach  = left;
                    var rightApproach = right;

                    {
                        NavMeshHit hit;
                        var        position = left + cover.Left * AISearch.CoverOffset;

                        if (NavMesh.Raycast(left, position, out hit, 1))
                        {
                            leftApproach = left;
                        }
                        else
                        {
                            leftApproach = position;
                        }
                    }

                    {
                        NavMeshHit hit;
                        var        position = right + cover.Right * AISearch.CoverOffset;

                        if (NavMesh.Raycast(right, position, out hit, 1))
                        {
                            rightApproach = right;
                        }
                        else
                        {
                            rightApproach = position;
                        }
                    }

                    if (cover.LeftAdjacent != null && cover.RightAdjacent != null)
                    {
                        leftApproach  = left;
                        rightApproach = right;
                    }
                    else if (cover.LeftAdjacent != null)
                    {
                        leftApproach = rightApproach;
                    }
                    else if (cover.RightAdjacent != null)
                    {
                        rightApproach = leftApproach;
                    }

                    possiblyAddRightPoint(ref index, new SearchPoint(left, leftApproach, -cover.Forward, false));

                    if (length > AISearch.BlockThreshold * 2)
                    {
                        possiblyAddRightPoint(ref index, new SearchPoint(left + vector * 0.2f, leftApproach, -cover.Forward, false));
                        possiblyAddRightPoint(ref index, new SearchPoint(left + vector * 0.4f, leftApproach, -cover.Forward, false));
                        possiblyAddRightPoint(ref index, new SearchPoint(left + vector * 0.6f, rightApproach, -cover.Forward, false));
                        possiblyAddRightPoint(ref index, new SearchPoint(left + vector * 0.8f, rightApproach, -cover.Forward, false));
                    }
                    else if (length > AISearch.BlockThreshold)
                    {
                        possiblyAddRightPoint(ref index, new SearchPoint(left + vector * 0.33f, leftApproach, -cover.Forward, false));
                        possiblyAddRightPoint(ref index, new SearchPoint(left + vector * 0.66f, rightApproach, -cover.Forward, false));
                    }

                    possiblyAddRightPoint(ref index, new SearchPoint(right, rightApproach, -cover.Forward, false));

                    if (cover.RightAdjacent != null && !_usedCovers.Contains(cover.RightAdjacent))
                    {
                        cover = cover.RightAdjacent;
                    }
                    else
                    {
                        cover = null;
                    }
                }
            }

            _zoneCache.Reset(Vector3.zero, searchRadius);

            for (int i = 0; i < _zoneCache.Items.Count; i++)
            {
                var block = _zoneCache.Items[i];

                foreach (var position in block.Points(AISearch.BlockThreshold))
                {
                    addPoint(new SearchPoint(position, false));
                }
            }
        }
Example #3
0
        private static void mergeBlocks()
        {
            int processed = 0;

            for (int a = _currentMergedGeneratedBlockId; a < _blocks.Count - 1; a++)
            {
RESTART:

                if (processed > 0)
                {
                    _currentMergedGeneratedBlockId = a;
                    break;
                }

                processed++;

                for (int b = _blocks.Count - 1; b > a; b--)
                {
                    for (int p = 0; p < _blocks[a].Indices.Count; p++)
                    {
                        var ap = _blocks[a].Indices[p];

                        if (_blocks[b].IsClose(_points.Points[ap], AISearch.BlockThreshold, AISearch.BlockCenterThreshold))
                        {
                            goto SUCCESS;
                        }
                    }

                    continue;

SUCCESS:

                    for (int p = 0; p < _blocks[b].Indices.Count; p++)
                    {
                        _blocks[a].Add(_blocks[b].Indices[p]);
                    }

                    _blockCache.Give(_blocks[b]);
                    _blocks.RemoveAt(b);

                    goto RESTART;
                }
            }

            for (int i = 0; i < _blocks.Count; i++)
            {
                var block = _blocks[i];
                block.Index = i;
                _blocks[i]  = block;
            }

            GeneratedPoints.Clear();
            _points.WriteTo(GeneratedPoints);

            for (int i = 0; i < _blocks.Count; i++)
            {
                var block = _blockCache.Take();
                _blocks[i].WriteTo(ref block);

                GeneratedBlocks.Add(block);
            }

            _isGenerating = false;
        }
Example #4
0
        private void Update()
        {
            for (int i = _investigated.Count - 1; i >= 0; i--)
            {
                if (_investigated[i].Time < Time.timeSinceLevelLoad - MaxInvestigationAge)
                {
                    _investigated.RemoveAt(i);
                }
            }

            if (!_isSearching)
            {
                return;
            }

            if (_blocks.Count == 0 && !_hasPoint)
            {
                ToClearSearchHistory();

                _hasPreviousPoint = false;
                _points.Clear();

                foreach (var block in _investigatedBlocks)
                {
                    _blockCache.Give(block);
                }

                _investigatedBlocks.Clear();
                _usedCovers.Clear();
                _coverCache.Reset(transform.position, MaxDistance, false);

                foreach (var item in _coverCache.Items)
                {
                    if (_usedCovers.Contains(item.Cover))
                    {
                        continue;
                    }

                    var cover = item.Cover;

                    while (cover.LeftAdjacent != null && !_usedCovers.Contains(cover.LeftAdjacent))
                    {
                        cover = cover.LeftAdjacent;
                    }

                    var index = -1;

                    while (cover != null)
                    {
                        _usedCovers.Add(cover);

                        var left   = cover.LeftCorner(cover.Bottom) - cover.Forward * 0.25f;
                        var right  = cover.RightCorner(cover.Bottom) - cover.Forward * 0.25f;
                        var vector = right - left;
                        var length = vector.magnitude;

                        var leftApproach  = left;
                        var rightApproach = right;

                        {
                            NavMeshHit hit;
                            var        position = left + cover.Left * CoverOffset;

                            if (NavMesh.Raycast(left, position, out hit, 1))
                            {
                                leftApproach = left;
                            }
                            else
                            {
                                leftApproach = position;
                            }
                        }

                        {
                            NavMeshHit hit;
                            var        position = right + cover.Right * CoverOffset;

                            if (NavMesh.Raycast(right, position, out hit, 1))
                            {
                                rightApproach = right;
                            }
                            else
                            {
                                rightApproach = position;
                            }
                        }

                        if (cover.LeftAdjacent != null && cover.RightAdjacent != null)
                        {
                            leftApproach  = left;
                            rightApproach = right;
                        }
                        else if (cover.LeftAdjacent != null)
                        {
                            leftApproach = rightApproach;
                        }
                        else if (cover.RightAdjacent != null)
                        {
                            rightApproach = leftApproach;
                        }

                        possiblyAddRightPoint(ref index, new SearchPoint(left, leftApproach, -cover.Forward, false));

                        if (length > Advanced.BlockThreshold * 2)
                        {
                            possiblyAddRightPoint(ref index, new SearchPoint(left + vector * 0.2f, leftApproach, -cover.Forward, false));
                            possiblyAddRightPoint(ref index, new SearchPoint(left + vector * 0.4f, leftApproach, -cover.Forward, false));
                            possiblyAddRightPoint(ref index, new SearchPoint(left + vector * 0.6f, rightApproach, -cover.Forward, false));
                            possiblyAddRightPoint(ref index, new SearchPoint(left + vector * 0.8f, rightApproach, -cover.Forward, false));
                        }
                        else if (length > Advanced.BlockThreshold)
                        {
                            possiblyAddRightPoint(ref index, new SearchPoint(left + vector * 0.33f, leftApproach, -cover.Forward, false));
                            possiblyAddRightPoint(ref index, new SearchPoint(left + vector * 0.66f, rightApproach, -cover.Forward, false));
                        }

                        possiblyAddRightPoint(ref index, new SearchPoint(right, rightApproach, -cover.Forward, false));

                        if (cover.RightAdjacent != null && !_usedCovers.Contains(cover.RightAdjacent))
                        {
                            cover = cover.RightAdjacent;
                        }
                        else
                        {
                            cover = null;
                        }
                    }
                }

                _zoneCache.Reset(transform.position, MaxDistance);

                foreach (var block in _zoneCache.Items)
                {
                    foreach (var position in block.Points(Advanced.BlockThreshold))
                    {
                        addPoint(new SearchPoint(position, false));
                    }
                }

                mergeBlocks();
            }

            if (DebugPoints)
            {
                foreach (var block in _blocks)
                {
                    debugBlock(block);
                }

                foreach (var block in _investigatedBlocks)
                {
                    debugBlock(block);
                }
            }

            if (_blocks.Count == 0 && !_hasPoint)
            {
                return;
            }

            if (_block.Empty && !_hasPoint)
            {
                var pickedIndex   = -1;
                var previousValue = 0f;

                for (int i = 0; i < _blocks.Count; i++)
                {
                    var vector    = _searchPosition - _blocks[i].Center;
                    var distance  = vector.magnitude;
                    var direction = vector / distance;

                    var value = distance;

                    if (_hasBlockDirection)
                    {
                        value *= -Vector3.Dot(direction, _blockDirection) * 0.5f + 1.5f;
                    }
                    else
                    {
                        value *= -Vector3.Dot(direction, _actor.HeadDirection) * 0.5f + 1.5f;
                    }

                    if (pickedIndex < 0 || value < previousValue)
                    {
                        pickedIndex   = i;
                        previousValue = value;
                    }
                }


                if (pickedIndex != -1)
                {
                    _block = _blocks[pickedIndex];

                    _blocks.RemoveAt(pickedIndex);
                    _investigatedBlocks.Add(_block);

                    _hasBlockDirection = true;
                    _blockDirection    = (_block.Center - _searchPosition).normalized;
                }
            }

            if (!_hasPoint)
            {
                int   index;
                float value;
                findBestPoint(_block, out index, out value);

                setPoint(_block.Indices[index]);
                _block.Investigate(index);
            }

            if (!_hasApproached && !shouldApproach(_point))
            {
                _hasApproached = true;

                if (_wasRunning)
                {
                    run();
                }
                else
                {
                    walk();
                }
            }

            if (_wasRunning && !shouldRunTo(_point.Position))
            {
                walk();
            }

            _checkWait -= Time.deltaTime;

            if (_checkWait <= float.Epsilon)
            {
                glimpse(_block);

                for (int b = _blocks.Count - 1; b >= 0; b--)
                {
                    glimpse(_blocks[b]);

                    if (_blocks[b].Empty)
                    {
                        _investigatedBlocks.Add(_blocks[b]);
                        _blocks.RemoveAt(b);
                    }
                }

                _checkWait = 0.25f;
            }

            if (DebugTarget)
            {
                Debug.DrawLine(transform.position, _point.Position, Color.yellow);
            }

            if (canBeInvestigated(_point))
            {
                var point = new InvestigatedPoint(_point.Position);
                _hasPoint = false;

                markInvestigated(point);

                foreach (var friend in _friends)
                {
                    friend.considerPoint(point);
                }
            }
        }