private static int DistanceToNode(AStarNode from, AStarNode to) { return(math.abs(to.XCoord - from.XCoord) + math.abs(to.YCoord - from.YCoord)); }
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; } } }
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); */ }