Пример #1
0
        /// <summary>
        /// Sets the node occupation at the node index. It can also be freed from any character that
        /// may be occupying it.
        /// </summary>
        /// <param name="nodeIndex"></param>
        /// <param name="occupiedReason"></param>
        public void SetNodeOccupation(int nodeIndex, NodeType occupiedReason)
        {
            if (NodeIndexOutOfBounds(nodeIndex))
            {
                Logger.LogWarning("Trying to occupy a node, but it is not possible because the node index is invalid.");
                return;
            }

            nodesTypes[nodeIndex] = occupiedReason;
        }
Пример #2
0
        /// <summary>
        /// Creates the grid of nodes.
        /// </summary>
        public void CreateGrid()
        {
            DestroyGrid();

            // TODO: Perhaps we might want to snap the extents value when editing the bounding box
            // in the editor?
            Bounds           scanBounds   = scanCollider.bounds;
            ScanAreaSettings scanSettings = new ScanAreaSettings((float3)scanBounds.center, (float3)scanBounds.extents, walkableMask);
            int expectedGridDimension     = scanSettings.gridDimension;

            // TODO: Could I use nodesTypes invalid to avoid any kind of computation from them?
            nodesTransforms = new NativeArray <NodeTransform>(expectedGridDimension, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
            nodesTypes      = new NativeArray <NodeType>(expectedGridDimension, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
            nodesNeighbors  = new NativeArray <NodeNeighbor>(expectedGridDimension * NodeNumNeighbors, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);

            // calculate the initial raycast commands
            NativeArray <RaycastCommand> mainCommands = new NativeArray <RaycastCommand>(expectedGridDimension, Allocator.TempJob);

            JobHandle createNodesHandle = new CalculateRaycastCommandsJob
            {
                commands     = mainCommands,
                scanSettings = scanSettings,
            }
            .ScheduleParallel(expectedGridDimension, 64, default(JobHandle));

            // schedule the commands to retrieve the initial hits
            NativeArray <RaycastHit> nodeHits = new NativeArray <RaycastHit>(expectedGridDimension, Allocator.TempJob);

            createNodesHandle = RaycastCommand.ScheduleBatch(mainCommands, nodeHits, 32, createNodesHandle);

            JobHandle.ScheduleBatchedJobs();

            // build the nodes using the received hits and the main raycast commands
            createNodesHandle = new CreateNodesJob
            {
                nodesTransforms = nodesTransforms,
                nodesTypes      = nodesTypes,
                hits            = nodeHits,
                commands        = mainCommands,
            }
            .ScheduleParallel(expectedGridDimension, 32, createNodesHandle);

            // calculate the boxcasts to bake obstacles
            NativeArray <BoxcastCommand> boxcastCommands = new NativeArray <BoxcastCommand>(expectedGridDimension, Allocator.TempJob);

            JobHandle bakeObstaclesHandle = new CalculateBoxcastCommandsJob
            {
                commands           = boxcastCommands,
                nodesTransforms    = nodesTransforms,
                mask               = obstacleMask,
                boxNodePercentage  = boxToNodeObstaclePercentage,
                maxCharacterHeight = maxCharacterHeight,
            }
            .ScheduleParallel(expectedGridDimension, 64, createNodesHandle);

            // schedule the boxcasts to find possible obstacles
            NativeArray <RaycastHit> obstacleHits = new NativeArray <RaycastHit>(expectedGridDimension, Allocator.TempJob);

            bakeObstaclesHandle = BoxcastCommand.ScheduleBatch(boxcastCommands, obstacleHits, 32, bakeObstaclesHandle);

            // prepare the bake obstacles job
            bakeObstaclesHandle = new BakeObstaclesJob
            {
                nodesTypes  = nodesTypes,
                boxcastHits = obstacleHits,
            }
            .ScheduleParallel(expectedGridDimension, 128, bakeObstaclesHandle);

            // now calculate the neighbors
            JobHandle calculateNeighborsHandle = new CalculateNeighborsJob
            {
                neighbors                 = nodesNeighbors,
                nodesTransforms           = nodesTransforms,
                scanSettings              = scanSettings,
                maxWalkableHeightWithStep = maxWalkableHeightWithStep,
            }
            .ScheduleParallel(expectedGridDimension, 32, createNodesHandle);

            JobHandle finalHandle = JobHandle.CombineDependencies(calculateNeighborsHandle, bakeObstaclesHandle);

            JobHandle disposeHandle = JobHandle.CombineDependencies(mainCommands.Dispose(finalHandle), nodeHits.Dispose(finalHandle));

            disposeHandle = JobHandle.CombineDependencies(disposeHandle, boxcastCommands.Dispose(finalHandle), obstacleHits.Dispose(finalHandle));

            // wait to complete all the scheduled stuff
            finalHandle.Complete();

            gridWidth     = scanSettings.gridWidth;
            gridDepth     = scanSettings.gridDepth;
            isGridCreated = true;

            OnGridCreation?.Invoke();

            Logger.LogFormat("Grid was created with dimension {0}. Width: {1}. Height: {2}.", expectedGridDimension, gridWidth, gridDepth);

            disposeHandle.Complete();
        }