Beispiel #1
0
        public void OnDestroy()
        {
            if (Watch != null)
            {
                Watch.Stop();
            }

            if (CrowdController != null)
            {
                CrowdController.OnDestroy();
            }


            NavMesh.Dispose();

            foreach (var inputBuilder in CurrentInputBuilders)
            {
                inputBuilder.Dispose();
            }
            CurrentInputBuilders.Clear();

            if (Colliders.IsCreated)
            {
                Colliders.Dispose();
            }
            if (TilesToBuild.IsCreated)
            {
                TilesToBuild.Dispose();
            }
            if (BuildInputs.IsCreated)
            {
                BuildInputs.Dispose();
            }
            if (CurrentTileStatus.IsCreated)
            {
                CurrentTileStatus.Dispose();
            }
            if (BoxFilters.IsCreated)
            {
                BoxFilters.Dispose();
            }
            if (HandlesToWaitFor.IsCreated)
            {
                HandlesToWaitFor.Dispose();
            }
            if (TilesSavedStatus.IsCreated)
            {
                TilesSavedStatus.Dispose();
            }
            MeshSourceMap.Dispose();

            RebuiltTilesHandle.Free();
            TilesHandle.Free();
        }
Beispiel #2
0
        public SurfaceController(SurfaceControllerConfig config, AiNavSystem system)
        {
            Config      = config;
            AiNavSystem = system;

            Builder = new NavMeshBuilder(Config.BuildSettings, Config.AgentSettings);

            Colliders         = new NativeList <PhysicsCollider>(Allocator.Persistent);
            TilesToBuild      = new NativeQueue <NavMeshTileBounds>(Allocator.Persistent);
            BuildInputs       = new NativeQueue <NavMeshBuildInput>(Allocator.Persistent);
            CurrentTileStatus = new NativeArray <int>(1, Allocator.Persistent);
            BoxFilters        = new NativeList <BoxFilter>(Allocator.Persistent);
            MeshSourceMap     = new MeshSourceMap(Builder.BuildSettings);
            TilesSavedStatus  = new NativeArray <int>(1, Allocator.Persistent);

            TilesHandle = GCHandle.Alloc(Tiles);
            TilesPtr    = GCHandle.ToIntPtr(TilesHandle);

            RebuiltTilesHandle = GCHandle.Alloc(RebuiltTiles);
            RebuiltTilesPtr    = GCHandle.ToIntPtr(RebuiltTilesHandle);

            NavMesh = new AiNavMesh(Builder.BuildSettings.TileSize, Builder.BuildSettings.CellSize);

            bool loaded = NavMeshStoreSystem.Instance.LoadTiles(Config.SurfaceId, Tiles);

            foreach (NavMeshTile tile in Tiles.Values)
            {
                NavMesh.AddOrReplaceTile(tile.Data);
            }

            if (Config.CrowdEnabled)
            {
                CrowdController = new CrowdController(NavMesh, this);
            }

            HandlesToWaitFor = new NativeList <JobHandle>(Allocator.Persistent);

            SurfaceData.Load(this);
        }
Beispiel #3
0
        public JobHandle OnUpdate(JobHandle inputDeps)
        {
            if (CrowdController != null)
            {
                inputDeps = CrowdController.OnUpdate(AiNavSystem, inputDeps);
            }


            if (!Building)
            {
                if (TilesSavedStatus[0] == 1)
                {
                    TilesSavedStatus[0] = 0;
                    OnBuildCompleted?.Invoke(Config.SurfaceId);
                }

                if (Builder.HasTilesToBuild)
                {
                    Watch    = System.Diagnostics.Stopwatch.StartNew();
                    Building = true;
                    Builder.GetDirtyTileBounds(TilesToBuild);
                    Builder.ClearTilesToBuild();
                    RebuiltTiles.Clear();
                    UnityEngine.Debug.LogFormat("Building {0} tiles", TilesToBuild.Count);
                }

                if (!Building)
                {
                    HandlesToWaitFor.Clear();
                }

                return(inputDeps);
            }

            int status = CurrentTileStatus[0];

            // No tiles building
            if (status == 0)
            {
                for (int i = 0; i < Config.BatchSize; i++)
                {
                    if (TilesToBuild.TryDequeue(out NavMeshTileBounds tileBounds))
                    {
                        tileBounds.Bounds.min.y = -1024f;
                        tileBounds.Bounds.max.y = 1024f;
                        tileBounds.Bounds.Expand(2f);

                        NavMeshNativeInputBuilder inputBuilder = new NavMeshNativeInputBuilder(tileBounds);

                        if (Config.IncludeUnityPhysicsGeometry)
                        {
                            CollectGeometryJob collectGeometryJob = new CollectGeometryJob
                            {
                                IncludeMask    = Config.IncludeMask,
                                BoxFilters     = BoxFilters,
                                TileBounds     = tileBounds,
                                InputBuilder   = inputBuilder,
                                GeometryFilter = Config.GeometryFilter
                            };
                            inputDeps = collectGeometryJob.ScheduleSingle(AiNavSystem, inputDeps);
                        }


                        CollectFromMeshSourcesJob collectFromMeshSources = new CollectFromMeshSourcesJob
                        {
                            IncludeMask       = Config.IncludeMask,
                            MeshSourceMap     = MeshSourceMap,
                            TileBounds        = tileBounds,
                            InputBuilder      = inputBuilder,
                            SharedMeshSources = AiNavSystem.MeshDatas
                        };
                        inputDeps = collectFromMeshSources.Schedule(inputDeps);

                        CurrentInputBuilders.Add(inputBuilder);
                        CurrentTileStatus[0] = 1;
                    }
                }

                if (CurrentInputBuilders.Count == 0)
                {
                    if (Building)
                    {
                        CurrentTileStatus[0] = 0;

                        if (RebuiltTiles.Count > 0)
                        {
                            var handle = JobHandle.CombineDependencies(HandlesToWaitFor);
                            handle.Complete();

                            foreach (NavMeshTile rebuiltTile in RebuiltTiles.Values)
                            {
                                Tiles[rebuiltTile.Coord] = rebuiltTile;
                                NavMesh.AddOrReplaceTile(rebuiltTile.Data);
                            }

                            SaveTilesJob saveTilesJob = new SaveTilesJob
                            {
                                TilesSavedStatus = TilesSavedStatus,
                                SurfaceId        = Config.SurfaceId,
                                TilesPtr         = TilesPtr
                            };
                            inputDeps = saveTilesJob.Schedule(inputDeps);
                        }

                        Watch.Stop();
                        UnityEngine.Debug.LogFormat("Build finished in {0} tilecount {1}", Watch.ElapsedMilliseconds, RebuiltTiles.Count);
                        RebuiltTiles.Clear();
                        Building = false;
                    }
                }

                return(inputDeps);
            }

            // collection done, build
            if (status == 1)
            {
                foreach (var inputBuilder in CurrentInputBuilders)
                {
                    if (inputBuilder.Vertices.Length > 0)
                    {
                        BuildInputs.Enqueue(inputBuilder.ToBuildInput());
                    }
                }

                BuildTileJob buildTileJob = new BuildTileJob
                {
                    AgentSettings   = Builder.AgentSettings,
                    BuildSettings   = Builder.BuildSettings,
                    BuildInputs     = BuildInputs,
                    RebuiltTilesPtr = RebuiltTilesPtr,
                    SurfaceId       = Config.SurfaceId
                };
                inputDeps = buildTileJob.Schedule(inputDeps);

                CurrentTileStatus[0] = 2;
                return(inputDeps);
            }

            // Tile builds finished
            if (status == 2)
            {
                foreach (var inputBuilder in CurrentInputBuilders)
                {
                    inputBuilder.Dispose();
                }
                CurrentInputBuilders.Clear();
                CurrentTileStatus[0] = 0;
            }

            return(inputDeps);
        }