示例#1
0
 private static int DistanceToNode(AStarNode from, AStarNode to)
 {
     return(math.abs(to.XCoord - from.XCoord) + math.abs(to.YCoord - from.YCoord));
 }
示例#2
0
            public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
            {
                NativeArray <NavigationGridData>  navigationGrids    = chunk.GetNativeArray(this.navigationGridType);
                BufferAccessor <AStarNodeElement> nodeBufferAccessor = chunk.GetBufferAccessor(this.nodeBufferType);

                for (int ci = 0, cn = chunk.Count; ci < cn; ci++)
                {
                    NavigationGridData navigationGrid           = outNavigationGrid[0] = navigationGrids[ci];
                    DynamicBuffer <AStarNodeElement> nodeBuffer = nodeBufferAccessor[ci];

                    // Solve path if requested

                    if (navigationGrid.pathRequested)
                    {
                        // All nodes
                        NativeArray <AStarNode> nodes = nodeBuffer.Reinterpret <AStarNode>().ToNativeArray(Allocator.Temp);

                        // Create temp grid
                        AStarGrid aStarGrid = new AStarGrid(navigationGrid.lengthX, navigationGrid.lengthY, nodes);

                        // Start/end nodes
                        AStarNode start = navigationGrid.pathStart;
                        AStarNode end   = navigationGrid.pathEnd;

                        // Solve path
                        NativeList <AStarNode> pathNodeList = new NativeList <AStarNode>(Allocator.Temp);
                        bool pathFound  = AStarSolver.SolvePath(aStarGrid, start, end, ref pathNodeList);
                        int  pathLength = pathNodeList.Length;
                        if (pathFound && navigationGrid.pathMustBeStraightLine)
                        {
                            // Check if path is straight line if specfied as a requirement
                            bool xDiverge = false;
                            bool yDiverge = false;
                            for (int i = 1, n = pathNodeList.Length; i < n; i++)
                            {
                                if (!xDiverge)
                                {
                                    xDiverge = pathNodeList[i].XCoord != pathNodeList[i - 1].XCoord;
                                }
                                if (!yDiverge)
                                {
                                    yDiverge = pathNodeList[i].YCoord != pathNodeList[i - 1].YCoord;
                                }
                                if (xDiverge && yDiverge)
                                {
                                    pathFound = false;
                                    break;
                                }
                            }
                        }


                        // Copy path node list to output array
                        NativeSlice <AStarNode> pathNodeListSlice = new NativeSlice <AStarNode>(pathNodeList.AsArray());
                        NativeSlice <AStarNode> pathNodeSlice     = new NativeSlice <AStarNode>(this.outPathNodes, 0, pathLength);
                        pathNodeSlice.CopyFrom(pathNodeListSlice);

                        // Dispose native containers
                        pathNodeList.Dispose();
                        aStarGrid.Dispose();
                        nodes.Dispose();

                        this.outPathFound[0]                  = pathFound ? 1 : 0;
                        this.outPathFound[1]                  = pathLength;
                        navigationGrid.pathRequested          = false;
                        navigationGrid.pathMustBeStraightLine = false;

                        // Apply changes
                        navigationGrids[ci] = navigationGrid;
                    }
                }
            }
示例#3
0
        public static bool SolvePath(AStarGrid grid, AStarNode start, AStarNode end, ref NativeList <AStarNode> pathNodes)
        {
            NativeList <AStarNode> openNodes   = new NativeList <AStarNode>(Allocator.Temp);
            NativeList <AStarNode> closedNodes = new NativeList <AStarNode>(Allocator.Temp);

            AStarNode current = start;

            openNodes.Add(start);

            bool pathFound = false;

            while (openNodes.Length > 0)
            {
                current = openNodes[0];
                int minF = current.F;
                for (int i = 1, n = openNodes.Length; i < n; i++)
                {
                    if (minF > openNodes[i].F)
                    {
                        current = openNodes[i];
                    }
                }

                closedNodes.Add(current);

                openNodes.RemoveAtSwapBack(openNodes.IndexOf(current));

                if (current.Equals(end))
                {
                    // Path to end found
                    pathFound = true;
                    break;
                }

                NativeArray <AStarNode> adjacentNodes = new NativeArray <AStarNode>(4, Allocator.Temp);
                int length = 0;
                GetAdjacentNodes(grid, current, ref adjacentNodes, out length);

                for (int i = 0; i < length; i++)
                {
                    AStarNode adjacent = adjacentNodes[i];

                    if (closedNodes.IndexOf(adjacent) < 0)
                    {
                        if (openNodes.IndexOf(adjacent) < 0)
                        {
                            adjacent.parentIndex = current.Index;
                            adjacent.G           = DistanceToNode(adjacent, end);
                            adjacent.H           = adjacent.TraversalCost + grid[adjacent.parentIndex].H;

                            openNodes.Add(adjacent);

                            grid[adjacent.XCoord, adjacent.YCoord] = adjacent;
                        }
                    }
                }

                adjacentNodes.Dispose();
            }

            if (pathFound)
            {
                while (current.parentIndex >= 0)
                {
                    pathNodes.Add(current);
                    current = grid[current.parentIndex];
                }
                pathNodes.Add(start);

                // Reverse
                for (int i = 0, i2 = pathNodes.Length - 1; i < i2; i++, i2--)
                {
                    AStarNode t = pathNodes[i];
                    pathNodes[i]  = pathNodes[i2];
                    pathNodes[i2] = t;
                }
            }

            openNodes.Dispose();
            closedNodes.Dispose();

            return(pathFound);
        }
        protected override void OnUpdate()
        {
            // TEMPORARY for testing

            bool gatherBlocks = Input.GetKeyDown(KeyCode.F);

            if (gatherBlocks)
            {
                NativeArray <Entity>             currentBlocks   = this.blocksQuery.ToEntityArray(Allocator.TempJob);
                NativeArray <Translation>        translations    = new NativeArray <Translation>(currentBlocks.Length, Allocator.TempJob);
                NativeArray <Rotation>           rotations       = new NativeArray <Rotation>(currentBlocks.Length, Allocator.TempJob);
                NativeArray <BlockTraversalData> blockTraversals = new NativeArray <BlockTraversalData>(currentBlocks.Length, Allocator.TempJob);
                NativeArray <BlockGridNodeData>  blockGridNodes  = new NativeArray <BlockGridNodeData>(currentBlocks.Length, Allocator.TempJob);

                Translation          playerStartTranslation = new Translation();
                Rotation             playerStartRotation    = new Rotation();
                PlayerNavigationNode playerStartNode        = new PlayerNavigationNode();

                for (int i = 0, n = currentBlocks.Length; i < n; i++)
                {
                    translations[i]    = this.EntityManager.GetComponentData <Translation>(currentBlocks[i]);
                    rotations[i]       = this.EntityManager.GetComponentData <Rotation>(currentBlocks[i]);
                    blockTraversals[i] = this.EntityManager.GetComponentData <BlockTraversalData>(currentBlocks[i]);
                    blockGridNodes[i]  = this.EntityManager.GetComponentData <BlockGridNodeData>(currentBlocks[i]);
                }

                Entities.WithAll <Tag_NavigationGrid>().WithoutBurst().ForEach(
                    (int entityInQueryIndex, DynamicBuffer <AStarNodeElement> nodeBuf, ref NavigationGridData navigationGrid) => {
                    nodeBuf.Clear();

                    float minX, maxX;
                    minX = maxX = translations[0].Value.x;
                    float minZ, maxZ;
                    minZ = maxZ = translations[0].Value.z;
                    for (int ti = 0, tn = translations.Length; ti < tn; ti++)
                    {
                        if (minX > translations[ti].Value.x)
                        {
                            minX = translations[ti].Value.x;
                        }
                        if (maxX < translations[ti].Value.x)
                        {
                            maxX = translations[ti].Value.x;
                        }
                        if (minZ > translations[ti].Value.z)
                        {
                            minZ = translations[ti].Value.z;
                        }
                        if (maxZ < translations[ti].Value.z)
                        {
                            maxZ = translations[ti].Value.z;
                        }
                    }
                    int lengthX = (int)(math.abs(maxX - minX) / GridConstants.BLOCK_SIZE) + 1;
                    int lengthY = (int)(math.abs(maxZ - minZ) / GridConstants.BLOCK_SIZE) + 1;

                    navigationGrid.worldBoundsMin = new float2(minX, minZ);
                    navigationGrid.worldBoundsMax = new float2(maxX, maxZ);
                    navigationGrid.lengthX        = lengthX;
                    navigationGrid.lengthY        = lengthY;

                    for (int ti = 0, tn = translations.Length; ti < tn; ti++)
                    {
                        int x, y;
                        navigationGrid.WorldToGridPosition(translations[ti].Value, out x, out y);
                        int i          = (y * lengthX) + x;
                        AStarNode node = new AStarNode(x, y, i, true);
                        nodeBuf.Add(node);

                        BlockGridNodeData gridNode = new BlockGridNodeData()
                        {
                            XCoord = x,
                            YCoord = y,
                            Index  = i,
                        };
                        this.EntityManager.SetComponentData <BlockGridNodeData>(currentBlocks[ti], gridNode);

                        if (blockTraversals[ti].blockType == BlockType.Start)
                        {
                            playerStartTranslation = translations[ti];
                            playerStartRotation    = rotations[ti];
                            playerStartNode        = new PlayerNavigationNode(x, y, i, translations[ti].Value);
                        }
                    }
                    ;
                })
                .Run();

                translations.Dispose();
                rotations.Dispose();
                blockTraversals.Dispose();
                blockGridNodes.Dispose();


                currentBlocks.Dispose();

                EntityCommandBuffer.Concurrent ecb = this.endSimulationEntitySystem.CreateCommandBuffer().ToConcurrent();

                BufferFromEntity <Child> childrenBuffer = GetBufferFromEntity <Child>(true);
                //Entities.WithAll<Tag_Block>().ForEach(
                //	(int entityInQueryIndex, Entity entity) => {
                //		EntityUtils.EnableEntityHierarchy(ref ecb, entityInQueryIndex, entity, childrenBuffer);
                //	})
                //.Schedule();

                Entities.WithAll <Tag_BlockGroup>().ForEach(
                    (int entityInQueryIndex, ref DynamicBuffer <EntityElement> entityBuff) => {
                    for (int i = 0, n = entityBuff.Length; i < n; i++)
                    {
                        EntityUtils.DisableEntityHierarchy(ref ecb, entityInQueryIndex, entityBuff[i], childrenBuffer);
                    }
                })
                .Schedule();

                this.endSimulationEntitySystem.AddJobHandleForProducer(this.Dependency);

                //ecb = this.endSimulationEntitySystem.CreateCommandBuffer().ToConcurrent();

                //Entities.WithAll<Tag_Block>().ForEach(
                //	(int entityInQueryIndex, ref BlockSwitchData blockSwitch) => {
                //		blockSwitch.Reset();
                //		blockSwitch.RefreshView(ref ecb, entityInQueryIndex);
                //	})
                //.Schedule();

                //this.endSimulationEntitySystem.AddJobHandleForProducer(this.Dependency);

                Entities.WithAll <Tag_Player>().WithoutBurst().ForEach(
                    (ref PlayerMovementData playerMovement, ref Translation translation, ref Rotation rotation) => {
                    translation = playerStartTranslation;
                    rotation    = playerStartRotation;
                    playerMovement.currentNode = playerStartNode;
                })
                .Run();
            }

            /*
             * bool generateBlocks = Input.GetKeyDown(KeyCode.Space);
             *
             * if (!generateBlocks) {
             *      return;
             * }
             *
             * EntityCommandBuffer.Concurrent ecb = this.endSimulationEntitySystem.CreateCommandBuffer().ToConcurrent();
             *
             * Entity prefab = BlockManager.Instance.BlockPrefabEntity;
             *
             * NativeArray<Entity> currentBlocks = this.blocksQuery.ToEntityArray(Allocator.TempJob);
             *
             * Entities.WithAll<Tag_NavigationGrid>().WithoutBurst().ForEach(
             *      (int entityInQueryIndex, DynamicBuffer<AStarNodeElement> nodeBuf, ref NavigationGridData navigationGrid) =>
             * {
             *      for (int i = 0, n = currentBlocks.Length; i < n; i++) {
             *              ecb.DestroyEntity(entityInQueryIndex, currentBlocks[i]);
             *      }
             *
             *      Unity.Mathematics.Random random = new Unity.Mathematics.Random((uint)System.DateTime.Now.Millisecond);
             *      int rand = 0;
             *
             *      bool pathFound = false;
             *
             *      NativeArray<AStarNode> nodes = new NativeArray<AStarNode>(navigationGrid.LinearLength, Allocator.Temp);
             *
             *      while (!pathFound) {
             *
             *              for (int y = 0; y < navigationGrid.lengthY; y++) {
             *                      for (int x = 0; x < navigationGrid.lengthX; x++) {
             *                              int i = (y * navigationGrid.lengthX) + x;
             *                              AStarNode node;
             *                              bool forceWalkable = (x == 0 && y == 0) || (x == navigationGrid.lengthX - 1 && y == navigationGrid.lengthY - 1);
             *                              if (!forceWalkable && random.NextInt(0, navigationGrid.emptyRandFactor) < ++rand) {
             *                                      rand = 0;
             *                                      node = new AStarNode(x, y, i, false);
             *
             *                              } else {
             *                                      node = new AStarNode(x, y, i, true);
             *                              }
             *
             *                              nodes[i] = node;
             *                      }
             *              }
             *
             *              // Create temp grid
             *              AStarGrid aStarGrid = new AStarGrid(navigationGrid.lengthX, navigationGrid.lengthY, nodes);
             *
             *              // Start/end nodes
             *              AStarNode start = nodes[0];
             *              AStarNode end = nodes[nodes.Length - 1];
             *
             *              // Solve path
             *              NativeList<AStarNode> pathNodeList = new NativeList<AStarNode>(Allocator.Temp);
             *              pathFound = AStarSolver.SolvePath(aStarGrid, start, end, ref pathNodeList);
             *
             *              pathNodeList.Dispose();
             *              aStarGrid.Dispose();
             *      }
             *
             *      nodeBuf.Clear();
             *
             *      for (int i = 0, n = nodes.Length; i < n; i++) {
             *              if (nodes[i].IsTraverseable) {
             *                      float3 position = new float3(nodes[i].XCoord * GridConstants.BLOCK_SIZE, 0, nodes[i].YCoord * GridConstants.BLOCK_SIZE);
             *
             *                      Entity block = ecb.Instantiate(entityInQueryIndex, prefab);
             *
             *                      Translation translation = new Translation();
             *                      translation.Value = position;
             *                      ecb.SetComponent<Translation>(entityInQueryIndex, block, translation);
             *              }
             *
             *              nodeBuf.Add(nodes[i]);
             *      }
             *
             *      navigationGrid.pathRequested = true;
             *      navigationGrid.pathStart = nodeBuf[0];
             *      navigationGrid.pathEnd = nodeBuf[nodeBuf.Length - 1];
             *
             * }).WithDeallocateOnJobCompletion(currentBlocks).ScheduleParallel();
             *
             * this.endSimulationEntitySystem.AddJobHandleForProducer(this.Dependency);
             */
        }