예제 #1
0
        public static void CompressBounds(System.Collections.Generic.List <Bounds> bounds, float error = 0.0001f)
        {
            if (bounds != null && bounds.Count > 1)
            {
                var foundNeighbor = false;
                var index         = 0;

                do
                {
                    for (var i = index; i < bounds.Count; i++)
                    {
                        foundNeighbor = false;
                        var a = bounds[i];

                        for (var j = i + 1; j < bounds.Count; j++)
                        {
                            var b = bounds[j];
                            if (BoundsCompressor.HasSharedSide(a, b, error) == true)
                            {
                                a.Encapsulate(b);
                                bounds[j] = a;
                                bounds[i] = bounds[index];

                                foundNeighbor = true;
                                ++index;
                                break;
                            }
                        }

                        if (foundNeighbor == true)
                        {
                            break;
                        }
                    }
                } while (foundNeighbor == true);


                if (index > 0)
                {
                    bounds.RemoveRange(0, index);
                }
            }
        }
        public override void ApplyBeforeConnections(Graph graph)
        {
            var navMeshGraph   = graph as NavMeshGraph;
            var graphBounds    = new Bounds(navMeshGraph.graphCenter, navMeshGraph.size);
            var graphHeightMin = navMeshGraph.minHeight;
            var graphHeightMax = navMeshGraph.maxHeight;
            var cache          = PoolDictionary <int, Item> .Spawn(100);

            var obstacles = PoolDictionary <int, System.Collections.Generic.List <Bounds> > .Spawn(3);

            foreach (var item in this.items)
            {
                cache.Add(item.requiredTile == null ? 0 : item.requiredTile.GetInstanceID(), item);
            }


            foreach (var pos in this.bounds.allPositionsWithin)
            {
                var worldPosition = this.tilemap.GetCellCenterWorld(pos) - this.tilemap.layoutGrid.cellGap;

                if (graphBounds.Contains(worldPosition) == false)
                {
                    continue;
                }

                var tile = this.tilemap.GetTile(pos);
                var id   = tile == null ? 0 : tile.GetInstanceID();

                if (cache.TryGetValue(id, out var item) == true)
                {
                    if (obstacles.TryGetValue(item.tag, out var list) == false)
                    {
                        list = new System.Collections.Generic.List <Bounds>();
                        obstacles[item.tag] = PoolList <Bounds> .Spawn(100);
                    }

                    list.Add(new Bounds(worldPosition,
                                        new Vector3(item.customSize == true ? item.size.x : this.tilemap.layoutGrid.cellSize.x,
                                                    item.customSize == true ? item.size.y : this.tilemap.layoutGrid.cellSize.y, item.height)));


                    if (item.height < graphHeightMin)
                    {
                        graphHeightMin = item.height;
                    }
                    if (item.height > graphHeightMax)
                    {
                        graphHeightMax = item.height;
                    }
                }
            }

            foreach (var kv in obstacles)
            {
                var count = kv.Value.Count;
                BoundsCompressor.CompressBounds(kv.Value, 0.05f);

                UnityEngine.Debug.Log($"Obstacles bounds compress from {count} to {kv.Value.Count}");

                foreach (var obstacle in kv.Value)
                {
                    var source = new UnityEngine.AI.NavMeshBuildSource {
                        area      = kv.Key,
                        shape     = UnityEngine.AI.NavMeshBuildSourceShape.Box,
                        transform = Matrix4x4.TRS(obstacle.center,
                                                  this.tilemap.transform.rotation,
                                                  this.tilemap.transform.lossyScale) * this.tilemap.orientationMatrix * this.tilemap.GetTransformMatrix(this.tilemap.WorldToCell(obstacle.center)),
                        size = obstacle.size,
                    };

                    navMeshGraph.AddBuildSource(source);
                }

                PoolList <Bounds> .Recycle(kv.Value);
            }

            navMeshGraph.SetMinMaxHeight(graphHeightMin, graphHeightMax);

            PoolDictionary <int, Item> .Recycle(ref cache);

            PoolDictionary <int, System.Collections.Generic.List <Bounds> > .Recycle(ref obstacles);
        }