Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

[Write Only] NativeContainer error.

Discussion in 'Entity Component System' started by MintTree117, Mar 17, 2020.

  1. MintTree117

    MintTree117

    Joined:
    Dec 2, 2018
    Posts:
    340
    I am getting the following error:

    The native container has been declared as [WriteOnly] in the job, but you are reading from it.

    This is my code.
    Code (CSharp):
    1.                     NativeList<float2> highLevelPath = FindHighLevelPathInGraph(
    2.                         jobIndex , startEdges , startPathKeys , startPaths , startGridPosition , endGridPosition );
    3.  
    4.                     if ( highLevelPath.Length == 0 )
    5.                     {
    6.                         pathIndexComponentData[ entity ] = new Path_Index { index = -1 };
    7.                         startEdges.Dispose();
    8.                         startPathKeys.Dispose();
    9.                         startPaths.Dispose();
    10.                         highLevelPath.Dispose();
    11.  
    12.                         return;
    13.                     }
    I get the error on the if-statement
     
    Last edited: Mar 17, 2020
  2. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    First of all - it's always true you compare same things.
     if ( highLevelPath.Length == highLevelPath.Length )


    Show more code - Job declaration, job definition.
    Show full error - which container cause that error.
     
    Last edited: Mar 17, 2020
  3. MintTree117

    MintTree117

    Joined:
    Dec 2, 2018
    Posts:
    340
    Edited, that was a copy-paste typo.

    Eror is from NativeList endPath, decalred on line 410, in the function FindHighLevelPathInGraph, which itself calls FindLowLevelPathInCluster many times which itself returns a NativeList, which is added to endPath.

    Code (CSharp):
    1.    private struct FindPathJob : IJobParallelFor
    2.     {
    3.         // Grid Data
    4.         [ReadOnly] public int heuristicBias;
    5.         [ReadOnly] public int numCells;
    6.         [ReadOnly] public int gridNumClusters;
    7.         [ReadOnly] public int gridCellSize;
    8.         [ReadOnly] public int clusterSize;
    9.         // CLUSTER
    10.         [ReadOnly] public NativeArray<int2> clusterEdgeRangeArray; // same length
    11.         [ReadOnly] public NativeArray<int> clusterEdgeIndexPointerArray; // same length
    12.         [ReadOnly] public NativeArray<int> clusterEdgeIndexArray;
    13.         // EDGE
    14.         [ReadOnly] public NativeArray<int> interEdgeIndexArray; // same length
    15.         [ReadOnly] public NativeArray<int2> intraEdgeRangeArray; // same length
    16.         [ReadOnly] public NativeArray<int2> intraPathRangeArray; // same length
    17.         [ReadOnly] public NativeArray<int2> intraPathPositionRangeArray;
    18.         [ReadOnly] public NativeArray<float2> intraPathPositionArray;
    19.         [ReadOnly] public NativeArray<int> intraEdgeIndexArray;
    20.         // NODE
    21.         [ReadOnly] public NativeArray<int2> nodePositionArray; // same length
    22.         [ReadOnly] public NativeArray<int2> nodeNeighbourRangeArray; // same length
    23.         [ReadOnly] public NativeArray<int> nodeWalkableArray; // same length
    24.         [ReadOnly] public NativeArray<int> nodeNeighbourArray;
    25.         // Entity Data
    26.         [ReadOnly] public NativeArray<float2> startWorldPositions;
    27.         [ReadOnly] public NativeArray<float2> endWorldPositions;
    28.         [ReadOnly] public NativeArray<Entity> entities;
    29.         // Entity Data To Write To
    30.         [NativeDisableContainerSafetyRestriction] public BufferFromEntity<Path_Position> pathPositionBuffer;
    31.         [NativeDisableContainerSafetyRestriction] public ComponentDataFromEntity<Path_Index> pathIndexComponentData;
    32.  
    33.         public void Execute( int jobIndex )
    34.         {
    35.             // Get the current entity
    36.             Entity entity = entities[ jobIndex ];
    37.             pathPositionBuffer[ entity ].Clear();
    38.             pathIndexComponentData[ entity ] = new Path_Index { index = -1 };
    39.  
    40.             // Get grid positions from world positions (float2 -> int2)
    41.             float2 startGridPositionAsFloat = new float2(
    42.                 startWorldPositions[ jobIndex ].x / gridCellSize ,
    43.                 startWorldPositions[ jobIndex ].y / gridCellSize );
    44.             float2 endGridPositionAsFloat = new float2(
    45.                 endWorldPositions[ jobIndex ].x / gridCellSize ,
    46.                 endWorldPositions[ jobIndex ].y / gridCellSize );
    47.             int2 startGridPosition = new int2(
    48.                 ( int ) math.round( startGridPositionAsFloat.x ) ,
    49.                 ( int ) math.round( startGridPositionAsFloat.y ) );
    50.             int2 endGridPosition = new int2(
    51.                 ( int ) math.round( endGridPositionAsFloat.x ) ,
    52.                 ( int ) math.round( endGridPositionAsFloat.y ) );
    53.             // Get the cluster positions from the grid positions
    54.             int2 startClusterPosition = new int2(
    55.                 startGridPosition.x / clusterSize ,
    56.                 startGridPosition.y / clusterSize );
    57.             int2 endClusterPosition = new int2(
    58.                 endGridPosition.x / clusterSize ,
    59.                 endGridPosition.y / clusterSize );
    60.  
    61.             // If the start and end positions are in different clusters
    62.             if ( !startClusterPosition.Equals( endClusterPosition ) )
    63.             {
    64.                 // Get the start and end node indexes from their grid cluster positions
    65.                 int clusterIndex = startClusterPosition.x + startClusterPosition.y * gridNumClusters;
    66.                 int2 clusterEdgeKey = clusterEdgeRangeArray[ clusterIndex ];
    67.              
    68.                 // First two are same lengh and index
    69.                 NativeList<int> startEdges = new NativeList<int>( Allocator.Temp );
    70.                 NativeList<int2> startPathKeys = new NativeList<int2>( Allocator.Temp );
    71.                 NativeList<float2> startPaths = new NativeList<float2>( Allocator.Temp );
    72.  
    73.                 // Check every edge in the cluster to see if we can reach it
    74.                 for ( int i = clusterEdgeKey.x; i < clusterEdgeKey.y; i++ )
    75.                 {
    76.                     int nodeIndex = clusterEdgeIndexArray[ i ];
    77.                     NativeList<float2> pathToEdge =
    78.                         FindLowLevelPathInCluster( jobIndex , startGridPosition , nodePositionArray[ nodeIndex ] , startClusterPosition );
    79.  
    80.                     if ( pathToEdge.Length > 0 )
    81.                     {
    82.                         int startIndex = startPaths.Length;
    83.  
    84.                         startEdges.Add( nodeIndex ); // Store the actual edge
    85.  
    86.                         for ( int j = 0; j < pathToEdge.Length; j++ )
    87.                             startPaths.Add( pathToEdge[ j ] ); // Store the path to the edge
    88.  
    89.                         startPathKeys.Add( new int2( startIndex , startPaths.Length ) ); // Store a key to the pathList
    90.                     }
    91.  
    92.                     pathToEdge.Dispose();
    93.                 }
    94.  
    95.                 // If there are no paths from start position to any of the edges in current cluster, break out
    96.                 if ( startEdges.Length == 0 )
    97.                 {
    98.                     pathIndexComponentData[ entity ] = new Path_Index { index = -1 };
    99.                     startEdges.Dispose();
    100.                     startPathKeys.Dispose();
    101.                     startPaths.Dispose();
    102.  
    103.                     return;
    104.                 }
    105.                 else
    106.                 {
    107.                     NativeList<float2> highLevelPath = FindHighLevelPathInGraph(
    108.                         jobIndex , startEdges , startPathKeys , startPaths , startGridPosition , endGridPosition );
    109.  
    110.                     //highLevelPath.
    111.  
    112.                     if ( highLevelPath.Length > 0 )
    113.                     {
    114.                         // Write final path to entity buffer
    115.                         for ( int i = 0; i < highLevelPath.Length; i++ )
    116.                         {
    117.                             pathPositionBuffer[ entity ].Add( new Path_Position { position = highLevelPath[ i ] } );
    118.                         }
    119.                         pathIndexComponentData[ entity ] = new Path_Index { index = pathPositionBuffer[ entity ].Length - 1 };
    120.  
    121.  
    122.                         highLevelPath.Dispose();
    123.                         startPathKeys.Dispose();
    124.                         startPaths.Dispose();
    125.                         startEdges.Dispose();
    126.  
    127.                         return;
    128.                     }
    129.                     else
    130.                     {
    131.                         pathIndexComponentData[ entity ] = new Path_Index { index = -1 };
    132.                         startEdges.Dispose();
    133.                         startPathKeys.Dispose();
    134.                         startPaths.Dispose();
    135.                         highLevelPath.Dispose();
    136.  
    137.                         return;
    138.                     }
    139.                 }
    140.             }
    141.             else // OTHERWISE, the start and end positions are in the same cluster, so just do a quick low-level a* search
    142.             {
    143.                 NativeList<float2> path = FindLowLevelPathInCluster( jobIndex , startGridPosition , endGridPosition , startClusterPosition );
    144.  
    145.                 if ( path.Length > 0 )
    146.                 {
    147.                     for ( int i = 0; i < path.Length; i++ )
    148.                     {
    149.                         pathPositionBuffer[ entity ].Add( new Path_Position { position = path[ i ] } );
    150.                     }
    151.                     pathIndexComponentData[ entity ] = new Path_Index { index = pathPositionBuffer[ entity ].Length - 1 };
    152.                 }
    153.                 else
    154.                 {
    155.                     pathIndexComponentData[ entity ] = new Path_Index { index = -1 };
    156.                 }
    157.  
    158.                 path.Dispose();
    159.  
    160.                 return;
    161.             }
    162.         }
    163.      
    164.         private NativeList<float2> FindLowLevelPathInCluster( int jobIndex , int2 startPosition , int2 endPosition , int2 clusterPosition )
    165.         {
    166.             #region DATA SETUP
    167.  
    168.             int pathNodeArraySize = clusterSize * clusterSize;
    169.  
    170.             // Node sets
    171.             NativeMinHeap openSet = new NativeMinHeap(); openSet.Initialize( pathNodeArraySize , 0 , pathNodeArraySize + 1 );
    172.             //NativeList<int> openSet = new NativeList<int>( Allocator.Temp );
    173.  
    174.             NativeArray<int> localIndexArray = new NativeArray<int>( pathNodeArraySize , Allocator.Temp );
    175.             NativeArray<int> graphIndexArray = new NativeArray<int>( pathNodeArraySize , Allocator.Temp );
    176.             NativeArray<int> parentArray = new NativeArray<int>( pathNodeArraySize , Allocator.Temp );
    177.             NativeArray<int> hCostArray = new NativeArray<int>( pathNodeArraySize , Allocator.Temp );
    178.             NativeArray<int> gCostArray = new NativeArray<int>( pathNodeArraySize , Allocator.Temp );
    179.             NativeArray<int> fCostArray = new NativeArray<int>( pathNodeArraySize , Allocator.Temp );
    180.             NativeArray<Blittable_Bool> openArray = new NativeArray<Blittable_Bool>( pathNodeArraySize , Allocator.Temp );
    181.             NativeArray<Blittable_Bool> closedArray = new NativeArray<Blittable_Bool>( pathNodeArraySize , Allocator.Temp );
    182.  
    183.             // Initialize nodes from ReadOnly grid array
    184.             for ( int localRow = 0; localRow < clusterSize; localRow++ )
    185.             {
    186.                 for ( int localCol = 0; localCol < clusterSize; localCol++ )
    187.                 {
    188.                     int localIndex = localCol + localRow * clusterSize;
    189.                     int graphCol = localCol + clusterSize * clusterPosition.x;
    190.                     int graphRow = localRow + clusterSize * clusterPosition.y;
    191.                     int graphArrayIndex = graphCol + graphRow * numCells;
    192.  
    193.                     localIndexArray[ localIndex ] = localIndex;
    194.                     graphIndexArray[ localIndex ] = graphArrayIndex;
    195.                     parentArray[ localIndex ] = -1;
    196.                     gCostArray[ localIndex ] = int.MaxValue;
    197.                     openArray[ localIndex ] = false;
    198.                     closedArray[ localIndex ] = false;
    199.                 }
    200.             }
    201.  
    202.             // Get and cache the start and end pathNodeIndices
    203.             int endNodeX = endPosition.x - clusterPosition.x * clusterSize;
    204.             int endNodeY = endPosition.y - clusterPosition.y * clusterSize;
    205.             int startNodeX = startPosition.x - clusterPosition.x * clusterSize;
    206.             int startNodeY = startPosition.y - clusterPosition.y * clusterSize;
    207.  
    208.             //UnityEngine.Debug.Log( "EndPosition " + endPosition );
    209.             //UnityEngine.Debug.Log( "EndX " + endNodeX + " EndY " + endNodeY );
    210.  
    211.             int endNodeIndex = endNodeX + endNodeY * clusterSize;
    212.             int startNodeIndex = startNodeX + startNodeY * clusterSize;
    213.  
    214.             // Initialize the starting pathNode
    215.             int hCost = ManhattenDistance( nodePositionArray[ graphIndexArray[ startNodeIndex ] ] , endPosition );
    216.             gCostArray[ startNodeIndex ] = 0;
    217.             hCostArray[ startNodeIndex ] = hCost;
    218.             fCostArray[ startNodeIndex ] = hCost;
    219.             openArray[ startNodeIndex ] = true;
    220.  
    221.             // Add the start pathNode to the openSet
    222.             openSet.Enqueue( startNodeIndex , hCost );
    223.             //openSet.Add( startNodeIndex );
    224.  
    225.             #endregion
    226.             #region SEARCH GRAPH
    227.  
    228.             while ( openSet.Length > 0 )
    229.             {
    230.                 // Cache the pathNodeIndex we are working with during this iteration
    231.                 int currentNodeIndex = openSet.DequeueMin( localIndexArray , closedArray );
    232.  
    233.                 /*int currentNodeIndex = openSet[ 0 ];
    234.                 int removeIndex = 0;
    235.                 for ( int i = 0; i < openSet.Length; i++ )
    236.                 {
    237.                     if ( openSet[ i ] < currentNodeIndex )
    238.                     {
    239.                         currentNodeIndex = openSet[ 0 ];
    240.                         removeIndex = i;
    241.                     }
    242.                 }
    243.                 openSet.RemoveAtSwapBack( removeIndex );*/
    244.  
    245.                 // Break if we reached our goal
    246.                 if ( currentNodeIndex == endNodeIndex )
    247.                     break;
    248.  
    249.                 openArray[ currentNodeIndex ] = false;
    250.                 closedArray[ currentNodeIndex ] = true;
    251.  
    252.                 int2 neighbourKey =
    253.                     nodeNeighbourRangeArray[ graphIndexArray[ currentNodeIndex ] ];
    254.  
    255.                 for ( int i = neighbourKey.x; i < neighbourKey.y; i++ )
    256.                 {
    257.                     int graphNeighbour = nodeNeighbourArray[ i ];
    258.                     int2 graphNeighbourPos = nodePositionArray[ graphNeighbour ];
    259.  
    260.                     // Get the local neighbour index
    261.                     int neighbourCol = graphNeighbourPos.x - clusterPosition.x * clusterSize;
    262.                     int neighbourRow = graphNeighbourPos.y - clusterPosition.y * clusterSize;
    263.                     int localNeighbourIndex = neighbourCol + neighbourRow * clusterSize;
    264.  
    265.                     // Skip if its closed (already searched)
    266.                     if ( closedArray[ localNeighbourIndex ] )
    267.                         continue;
    268.  
    269.                     // Calculate the cost to move from current node to neighbour node
    270.                     int distanceCost = ManhattenDistance(
    271.                         nodePositionArray[ graphIndexArray[ currentNodeIndex ] ] , graphNeighbourPos );
    272.  
    273.                     int tentativeCost = gCostArray[currentNodeIndex] + distanceCost;
    274.  
    275.                     if ( tentativeCost < gCostArray[ localNeighbourIndex ] )
    276.                     {
    277.                         int newHCost = ManhattenDistance( graphNeighbourPos , endPosition );
    278.  
    279.                         parentArray[ localNeighbourIndex ] = currentNodeIndex;
    280.                         hCostArray[ localNeighbourIndex ] = newHCost;
    281.                         gCostArray[ localNeighbourIndex ] = tentativeCost;
    282.                         fCostArray[ localNeighbourIndex ] = tentativeCost + hCost;
    283.  
    284.                         if ( !openArray[ localNeighbourIndex ] )
    285.                         {
    286.                             openArray[ localNeighbourIndex ] = true;
    287.                             openSet.Enqueue( localNeighbourIndex , fCostArray[ localNeighbourIndex ] );
    288.                             //openSet.Add( localNeighbourIndex );
    289.                         }
    290.                     }
    291.                 }
    292.             }
    293.  
    294.             #endregion
    295.             #region TRACE PATH
    296.  
    297.             NativeList<int2> aStarPath = new NativeList<int2>( Allocator.Temp );
    298.             NativeList<float2> waypoints = new NativeList<float2>( Allocator.Temp );
    299.             int nodeIndex = endNodeIndex;
    300.  
    301.             if ( parentArray[ nodeIndex ] == -1 )
    302.             {
    303.                 openSet.Dispose();
    304.                 localIndexArray.Dispose();
    305.                 graphIndexArray.Dispose();
    306.                 parentArray.Dispose();
    307.                 hCostArray.Dispose();
    308.                 gCostArray.Dispose();
    309.                 fCostArray.Dispose();
    310.                 openArray.Dispose();
    311.                 closedArray.Dispose();
    312.                 aStarPath.Dispose();
    313.  
    314.                 return waypoints;
    315.             }
    316.  
    317.             waypoints.Add( endWorldPositions[ jobIndex ] );
    318.             aStarPath.Add( endPosition );
    319.  
    320.             while ( parentArray[ nodeIndex ] != -1 )
    321.             {
    322.                 aStarPath.Add( nodePositionArray[ graphIndexArray[ parentArray[ nodeIndex ] ] ] );
    323.                 nodeIndex = parentArray[ nodeIndex ];
    324.             }
    325.  
    326.             #endregion
    327.             #region SMOOTH PATH
    328.  
    329.             if ( aStarPath.Length > 2 ) // If its less than or equal 2 theres no need to smooth the path
    330.             {
    331.                 int fromIndex = 0;
    332.                 bool foundPath = false;
    333.  
    334.                 while ( !foundPath )
    335.                 {
    336.                     int currentIndex = fromIndex + 2; // Because the next index is always going to be in line of sight
    337.  
    338.                     if ( currentIndex > aStarPath.Length - 1 )
    339.                         break;
    340.  
    341.                     while ( true )
    342.                     {
    343.                         int stopIndex = currentIndex - 1;
    344.                         int graphNodeArrayIndex = aStarPath[ stopIndex ].x + aStarPath[ stopIndex ].y * numCells;
    345.  
    346.                         int2 start = aStarPath[ fromIndex ];
    347.                         int2 end = aStarPath[ currentIndex ];
    348.  
    349.                         if ( !LOS( start.x , start.y , end.x , end.y ) )
    350.                         {
    351.                             float2 worldPosition = new float2(
    352.                                 nodePositionArray[ graphNodeArrayIndex ].x * gridCellSize ,
    353.                                 nodePositionArray[ graphNodeArrayIndex ].y * gridCellSize );
    354.  
    355.                             waypoints.Add( worldPosition );
    356.                             fromIndex = stopIndex;
    357.                             break;
    358.                         }
    359.                         else
    360.                         {
    361.                             if ( currentIndex >= aStarPath.Length - 1 )
    362.                             {
    363.                                 foundPath = true;
    364.                                 break;
    365.                             }
    366.                             currentIndex++;
    367.                         }
    368.                     }
    369.                 }
    370.             }
    371.  
    372.             #endregion
    373.             #region RETURN
    374.  
    375.             openSet.Dispose();
    376.             localIndexArray.Dispose();
    377.             graphIndexArray.Dispose();
    378.             parentArray.Dispose();
    379.             hCostArray.Dispose();
    380.             gCostArray.Dispose();
    381.             fCostArray.Dispose();
    382.             openArray.Dispose();
    383.             closedArray.Dispose();
    384.             aStarPath.Dispose();
    385.             return waypoints;
    386.  
    387.             #endregion
    388.         }
    389.         private NativeList<float2> FindHighLevelPathInGraph(
    390.             int jobIndex , NativeList<int> startEdges , NativeList<int2> startPathsKeys , NativeList<float2> startPathsPositions , int2 startPosition , int2 endPosition )
    391.         {
    392.             #region DATA SETUP
    393.  
    394.             int edgeArraySize = clusterEdgeIndexArray.Length;
    395.  
    396.             // Node sets
    397.             NativeMinHeap openSet = new NativeMinHeap(); openSet.Initialize( edgeArraySize , -1 , edgeArraySize + 10 );
    398.             // Shares indices with clusterEdgeIndexArray
    399.             NativeArray<int> nodeIndexArray = new NativeArray<int>( edgeArraySize , Allocator.Temp );
    400.             NativeArray<int> parentArray = new NativeArray<int>( edgeArraySize , Allocator.Temp );
    401.             NativeArray<int2> fromPaths = new NativeArray<int2>( edgeArraySize , Allocator.Temp );
    402.             NativeArray<int> startEdgesIndexes = new NativeArray<int>( startEdges.Length , Allocator.Temp );
    403.             NativeArray<int> hCostArray = new NativeArray<int>( edgeArraySize , Allocator.Temp );
    404.             NativeArray<int> gCostArray = new NativeArray<int>( edgeArraySize , Allocator.Temp );
    405.             NativeArray<int> fCostArray = new NativeArray<int>( edgeArraySize , Allocator.Temp );
    406.             NativeArray<Blittable_Bool> openArray = new NativeArray<Blittable_Bool>( edgeArraySize , Allocator.Temp );
    407.             NativeArray<Blittable_Bool> closedArray = new NativeArray<Blittable_Bool>( edgeArraySize , Allocator.Temp );
    408.  
    409.             // To store the low-level path in the last cluster
    410.             NativeList<float2> endPath = new NativeList<float2>( Allocator.Temp );
    411.  
    412.             // Initialize nodes from ReadOnly grid array
    413.             for ( int i = 0; i < edgeArraySize; i++ )
    414.             {
    415.                 nodeIndexArray[ i ] = clusterEdgeIndexArray[ i ];
    416.                 parentArray[ i ] = -1;
    417.                 gCostArray[ i ] = int.MaxValue;
    418.                 openArray[ i ] = false;
    419.                 closedArray[ i ] = false;
    420.             }
    421.  
    422.             // Initialize the starting nodes(edges) from the parameter
    423.             for ( int i = 0; i < startEdges.Length; i++ )
    424.             {
    425.                 int localIndex = clusterEdgeIndexPointerArray[ startEdges[ i ] ];
    426.                 hCostArray[ localIndex ] = ManhattenDistance( nodePositionArray[ startEdges[ i ] ] , endPosition );
    427.                 int2 pathKey = startPathsKeys[ i ];
    428.                 gCostArray[ localIndex ] = pathKey.y - pathKey.x; // The length of the path
    429.                 fCostArray[ localIndex ] = gCostArray[ localIndex ] + hCostArray[ localIndex ];
    430.                 startEdgesIndexes[ i ] = localIndex; // Saving the start edges to trace path later
    431.  
    432.                 openSet.Enqueue( localIndex , fCostArray[ localIndex ] );
    433.             }
    434.  
    435.             // So we can test wehn we reached the end
    436.             int2 endClusterPosition = new int2(
    437.                 endPosition.x / clusterSize ,
    438.                 endPosition.y / clusterSize );
    439.  
    440.             int localEndNodeIndex = -1;
    441.  
    442.             #endregion
    443.             #region SEARCH GRAPH
    444.  
    445.             while ( openSet.Length > 0 )
    446.             {
    447.                 int currentLocalIndex = openSet.DequeueMin( closedArray );
    448.                 int currentNodeIndex = nodeIndexArray[currentLocalIndex];
    449.                 //int currentLocalIndex = clusterEdgeIndexPointerArray[ currentNodeIndex ];
    450.  
    451.                 int2 clusterPosition = new int2(
    452.                     nodePositionArray[ currentNodeIndex ].x / clusterSize ,
    453.                     nodePositionArray[ currentNodeIndex ].y / clusterSize );
    454.  
    455.                 // If we have reached the end cluster, try to find a low level path to end position
    456.                 if ( clusterPosition.Equals( endClusterPosition ) )
    457.                 {
    458.                     UnityEngine.Debug.Log( "Reached endClusterPosition" );
    459.  
    460.                     int2 startPathPosition = nodePositionArray[ currentNodeIndex ];
    461.                     endPath.Clear();
    462.                     endPath = FindLowLevelPathInCluster( jobIndex , startPathPosition , endPosition , clusterPosition );
    463.  
    464.                     // Break out of the loop if we have a low-level path to the endPosition
    465.                     if ( endPath.Length > 0 )
    466.                     {
    467.                         localEndNodeIndex = currentLocalIndex;
    468.                         break;
    469.                     }
    470.                 }
    471.  
    472.                 // Search our neighbour edges/paths
    473.                 int2 edgesRange = intraEdgeRangeArray[ currentNodeIndex ];
    474.                 // Loop over every edge (intraEdgeIndexArray within range of edgeRange)
    475.                 for ( int i = edgesRange.x; i < edgesRange.y; i++ )
    476.                 {
    477.                     int neighbourEdgeNodeIndex = intraEdgeIndexArray[ i ];
    478.                     int localNeighbourIndex = clusterEdgeIndexPointerArray[ neighbourEdgeNodeIndex ];
    479.  
    480.                     if ( closedArray[ localNeighbourIndex ] )
    481.                         continue;
    482.  
    483.                     int gCost = gCostArray[ localNeighbourIndex ];
    484.                     //int pathPositionRangeIndex = pathRange[ i ];
    485.                     int2 pathPositionRange = intraPathPositionRangeArray[ i ];
    486.                     int distanceCost = pathPositionRange.y - pathPositionRange.x;
    487.                     int tentativeCost = gCost + distanceCost;
    488.  
    489.                     if ( tentativeCost < gCostArray[ localNeighbourIndex ] )
    490.                     {
    491.                         parentArray[ localNeighbourIndex ] = currentLocalIndex;
    492.                         // This is to trace path at the end
    493.                         fromPaths[ localNeighbourIndex ] = pathPositionRange;
    494.                         hCostArray[ localNeighbourIndex ] = ManhattenDistance(
    495.                             nodePositionArray[ neighbourEdgeNodeIndex ] , endPosition );
    496.                         gCostArray[ localNeighbourIndex ] = tentativeCost;
    497.                         fCostArray[ localNeighbourIndex ] = hCostArray[ localNeighbourIndex ] + gCostArray[ localNeighbourIndex ];
    498.  
    499.                         if ( !openArray[ localNeighbourIndex ] )
    500.                         {
    501.                             openArray[ localNeighbourIndex ] = true;
    502.                             openSet.Enqueue( localNeighbourIndex , fCostArray[ localNeighbourIndex ] );
    503.                         }
    504.                     }
    505.                 }
    506.             }
    507.  
    508.             #endregion
    509.             #region TRACE PATH
    510.  
    511.             if ( endPath.Length == 0 )
    512.             {
    513.                 openSet.Dispose();
    514.                 nodeIndexArray.Dispose();
    515.                 parentArray.Dispose();
    516.                 fromPaths.Dispose();
    517.                 startEdgesIndexes.Dispose();
    518.                 hCostArray.Dispose();
    519.                 gCostArray.Dispose();
    520.                 fCostArray.Dispose();
    521.                 openArray.Dispose();
    522.                 closedArray.Dispose();
    523.  
    524.                 UnityEngine.Debug.Log( "EndPath Length Is 0" );
    525.  
    526.                 return endPath;
    527.             }
    528.  
    529.             int currentIndex = localEndNodeIndex;
    530.             int parentIndex = parentArray[ currentIndex ];
    531.  
    532.             // Trace the cached paths back through high level graph
    533.             while ( parentIndex != -1 )
    534.             {
    535.                 int2 fromPathPositionRange = fromPaths[ currentIndex ];
    536.  
    537.                 for ( int i = fromPathPositionRange.y; i >= fromPathPositionRange.x; --i )
    538.                     endPath.Add( intraPathPositionArray[ i ] );
    539.  
    540.                 currentIndex = parentIndex;
    541.                 parentIndex = parentArray[ localEndNodeIndex ];
    542.             }
    543.  
    544.             // Find the starting edge
    545.             int startEdgeIndex = -1;
    546.             for ( int i = 0; i < startEdgesIndexes.Length; i++ )
    547.             {
    548.                 if ( startEdgesIndexes[ i ] == currentIndex )
    549.                 {
    550.                     startEdgeIndex = i;
    551.                     break;
    552.                 }
    553.             }
    554.  
    555.             // Trace the starting path from starting edge
    556.             int2 pathPositionKey = startPathsKeys[ startEdgeIndex ];
    557.             for ( int i = pathPositionKey.x; i < pathPositionKey.y; i++ )
    558.                 endPath.Add( startPathsPositions[ i ] );
    559.  
    560.             #endregion
    561.             #region RETURN
    562.  
    563.             openSet.Dispose();
    564.             nodeIndexArray.Dispose();
    565.             parentArray.Dispose();
    566.             fromPaths.Dispose();
    567.             startEdgesIndexes.Dispose();
    568.             hCostArray.Dispose();
    569.             gCostArray.Dispose();
    570.             fCostArray.Dispose();
    571.             openArray.Dispose();
    572.             closedArray.Dispose();
    573.  
    574.             return endPath;
    575.  
    576.             #endregion
    577.         }
    578.         private bool LOS( int x1 , int y1 , int x2 , int y2 )
    579.         {
    580.             int dx = math.abs( x2 - x1 );
    581.             int dy = math.abs( y2 - y1 );
    582.             int x = x1;
    583.             int y = y1;
    584.             int n = 1 + dx + dy;
    585.             int xInc = ( x2 > x1 ) ? 1 : -1;
    586.             int yInc = ( y2 > y1 ) ? 1 : -1;
    587.             int error = dx - dy;
    588.             int walkable = 0;
    589.  
    590.             bool prevY = false;
    591.  
    592.             if ( error <= 0 )
    593.             {
    594.                 prevY = true;
    595.             }
    596.  
    597.             int numSameDir = 0;
    598.  
    599.             dx *= 2;
    600.             dy *= 2;
    601.  
    602.             for ( ; n > 0; --n )
    603.             {
    604.                 walkable += nodeWalkableArray[ x + y * numCells ];
    605.  
    606.                 if ( numSameDir < 1 )
    607.                 {
    608.                     if ( prevY )
    609.                     {
    610.                         walkable += nodeWalkableArray[ ( x - xInc ) + y * numCells ];
    611.  
    612.                     }
    613.                     else
    614.                     {
    615.                         walkable += nodeWalkableArray[ x + ( y - yInc ) * numCells ];
    616.                     }
    617.                 }
    618.  
    619.                 if ( error > 0 ) // more steps in x
    620.                 {
    621.                     x += xInc;
    622.  
    623.                     if ( !prevY )
    624.                     {
    625.                         numSameDir++;
    626.                     }
    627.                     else
    628.                     {
    629.                         numSameDir = 0;
    630.                     }
    631.  
    632.                     prevY = false;
    633.                     error -= dy;
    634.                 }
    635.                 else // more steps in y
    636.                 {
    637.                     y += yInc;
    638.  
    639.                     if ( prevY )
    640.                     {
    641.                         numSameDir++;
    642.                     }
    643.                     else
    644.                     {
    645.                         numSameDir = 0;
    646.                     }
    647.  
    648.                     prevY = true;
    649.                     error += dx;
    650.                 }
    651.             }
    652.  
    653.             return walkable == 0;
    654.         }
    655.         private int ManhattenDistance( int2 positionA , int2 positionB )
    656.         {
    657.             int2 distance = positionB - positionA;
    658.             return math.abs( distance.x ) + math.abs( distance.y );
    659.         }
    660.     }
     
    deus0 likes this.