Advertisement
443eb9

Untitled

Sep 12th, 2023
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.75 KB | None | 0 0
  1. using HexagonSurvive.Game.Character.ECS;
  2. using HexagonSurvive.Map.Aspects;
  3. using HexagonSurvive.Map.Components;
  4. using Unity.Burst;
  5. using Unity.Collections;
  6. using Unity.Collections.LowLevel.Unsafe;
  7. using Unity.Entities;
  8. using Unity.Mathematics;
  9. using UnityEngine;
  10.  
  11. namespace HexagonSurvive.Game.Navigation
  12. {
  13.     [BurstCompile]
  14.     public partial struct PathFindingJob : IJobEntity
  15.     {
  16.         [NativeDisableUnsafePtrRestriction]
  17.         private RefRW<HexMapContainerData> _map;
  18.  
  19.         private const int MaxSearchStep = 100;
  20.  
  21.         public PathFindingJob(RefRW<HexMapContainerData> container) : this()
  22.         {
  23.             _map = container;
  24.         }
  25.  
  26.         private void Execute(CharacterAspect character, ref DynamicBuffer<PathBuffer> path)
  27.         {
  28.             RefRW<PathFindingTaskData> taskData = character.pathFindingTask;
  29.             int3 origin = taskData.ValueRO.origin;
  30.             PathUnit destination = new PathUnit { coordinate = taskData.ValueRO.dest };
  31.             bool ignoreNonWalkable = taskData.ValueRO.ignoreNonWalkable;
  32.             int curStepNum = 0;
  33.  
  34.             NativeHashSet<int3> explored = new NativeHashSet<int3>(8, Allocator.TempJob);
  35.             NativeList<int3> toExplore = new NativeList<int3>(Allocator.TempJob);
  36.             NativeHashMap<int3, PathUnit> pathRecords = new NativeHashMap<int3, PathUnit>(8, Allocator.TempJob);
  37.  
  38.             toExplore.Add(taskData.ValueRO.origin);
  39.             pathRecords.Add(taskData.ValueRO.origin, new PathUnit(0, default, taskData.ValueRO.origin, destination.coordinate));
  40.  
  41.             while (toExplore.Length != 0)
  42.             {
  43.                 int cur = FindBestUnit(toExplore, pathRecords);
  44.                 PathUnit curUnit = pathRecords[toExplore[cur]];
  45.  
  46.                 if ((curUnit.coordinate == destination.coordinate) is { x: true, y: true, z: true })
  47.                 {
  48.                     while ((curUnit.coordinate == origin) is not { x: true, y: true, z: true })
  49.                     {
  50.                         path.Add(new PathBuffer { coord = curUnit.coordinate });
  51.                         curUnit = pathRecords[curUnit.prior];
  52.                     }
  53.  
  54.                     Debug.LogError($"寻路完成: 长度{path.Length}");
  55.                     Complete(character, explored, toExplore, pathRecords);
  56.                     return;
  57.                 }
  58.  
  59.                 if (curStepNum == MaxSearchStep)
  60.                 {
  61.                     Debug.LogError($"未找到合适路径");
  62.                     Complete(character, explored, toExplore, pathRecords);
  63.                     return;
  64.                 }
  65.  
  66.                 explored.Add(toExplore[cur]);
  67.                 toExplore.RemoveAtSwapBack(cur);
  68.                 curStepNum++;
  69.  
  70.                 foreach (int3 coord in curUnit.GetNeighbours())
  71.                 {
  72.                     if (!_map.ValueRW.map.TryGetValue(coord, out HexUnitAspect u)) return;
  73.                     // InvalidOperationException: The ComponentLookup<HexagonSurvive.Map.Components.HexUnitData> has been declared as [WriteOnly] in the job, but you are reading from it. ↓↓↓↓↓
  74.                     if ((!ignoreNonWalkable && !u.Data.walkable) || explored.Contains(coord)) continue;
  75.  
  76.                     bool alreadyScheduled = toExplore.Contains(coord);
  77.                     pathRecords.TryAdd(coord, new PathUnit(int.MaxValue, default, coord, destination.coordinate));
  78.  
  79.                     if (!alreadyScheduled || curUnit.G + 1 < pathRecords[coord].G)
  80.                     {
  81.                         PathUnit newUnit = pathRecords[coord];
  82.                         newUnit.G = curUnit.G + 1;
  83.                         newUnit.H = PathUnit.GetUnitDistance(newUnit.coordinate, destination.coordinate);
  84.                         newUnit.prior = curUnit.coordinate;
  85.                         pathRecords[coord] = newUnit;
  86.  
  87.                         if (!alreadyScheduled)
  88.                             toExplore.Add(coord);
  89.                     }
  90.                 }
  91.             }
  92.         }
  93.  
  94.         private int FindBestUnit(NativeList<int3> toExplore, NativeHashMap<int3, PathUnit> pathRecords)
  95.         {
  96.             int best = 0;
  97.  
  98.             for (int i = 0; i < toExplore.Length; i++)
  99.                 if (pathRecords[toExplore[i]].CompareTo(pathRecords[toExplore[best]]) == -1)
  100.                     best = i;
  101.  
  102.             return best;
  103.         }
  104.  
  105.         private void Complete(CharacterAspect character, NativeHashSet<int3> explored,
  106.             NativeList<int3> toExplore, NativeHashMap<int3, PathUnit> pathRecords)
  107.         {
  108.             character.pathFindingTask.ValueRW.isReady = false;
  109.             character.pathFindingTask.ValueRW.isComplete = true;
  110.  
  111.             toExplore.Dispose();
  112.             explored.Dispose();
  113.             pathRecords.Dispose();
  114.         }
  115.     }
  116. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement