PathfindingComponentSystem.cs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using DotRecast.Core;
  5. using DotRecast.Detour;
  6. using DotRecast.Detour.Io;
  7. using Unity.Mathematics;
  8. namespace ET
  9. {
  10. [EntitySystemOf(typeof(PathfindingComponent))]
  11. public static partial class PathfindingComponentSystem
  12. {
  13. [EntitySystem]
  14. private static void Awake(this PathfindingComponent self, string name)
  15. {
  16. self.Name = name;
  17. byte[] buffer = NavmeshComponent.Instance.Get(name);
  18. DtMeshSetReader reader = new();
  19. using MemoryStream ms = new(buffer);
  20. using BinaryReader br = new(ms);
  21. self.navMesh = reader.Read32Bit(br, 6); // cpp recast导出来的要用Read32Bit读取,DotRecast导出来的还没试过
  22. if (self.navMesh == null)
  23. {
  24. throw new Exception($"nav load fail: {name}");
  25. }
  26. self.filter = new DtQueryDefaultFilter();
  27. self.query = new DtNavMeshQuery(self.navMesh);
  28. }
  29. [EntitySystem]
  30. private static void Destroy(this PathfindingComponent self)
  31. {
  32. self.Name = string.Empty;
  33. self.navMesh = null;
  34. }
  35. public static void Find(this PathfindingComponent self, float3 start, float3 target, List<float3> result)
  36. {
  37. if (self.navMesh == null)
  38. {
  39. Log.Debug("寻路| Find 失败 pathfinding ptr is zero");
  40. throw new Exception($"pathfinding ptr is zero: {self.Scene().Name}");
  41. }
  42. RcVec3f startPos = new(-start.x, start.y, start.z);
  43. RcVec3f endPos = new(-target.x, target.y, target.z);
  44. long startRef;
  45. long endRef;
  46. RcVec3f startPt;
  47. RcVec3f endPt;
  48. self.query.FindNearestPoly(startPos, self.extents, self.filter, out startRef, out startPt, out _);
  49. self.query.FindNearestPoly(endPos, self.extents, self.filter, out endRef, out endPt, out _);
  50. self.query.FindPath(startRef, endRef, startPt, endPt, self.filter, ref self.polys, new DtFindPathOption(0, float.MaxValue));
  51. if (0 >= self.polys.Count)
  52. {
  53. return;
  54. }
  55. // In case of partial path, make sure the end point is clamped to the last polygon.
  56. RcVec3f epos = RcVec3f.Of(endPt.x, endPt.y, endPt.z);
  57. if (self.polys[^1] != endRef)
  58. {
  59. DtStatus dtStatus = self.query.ClosestPointOnPoly(self.polys[^1], endPt, out RcVec3f closest, out bool _);
  60. if (dtStatus.Succeeded())
  61. {
  62. epos = closest;
  63. }
  64. }
  65. self.query.FindStraightPath(startPt, epos, self.polys, ref self.straightPath, PathfindingComponent.MAX_POLYS, DtNavMeshQuery.DT_STRAIGHTPATH_ALL_CROSSINGS);
  66. for (int i = 0; i < self.straightPath.Count; ++i)
  67. {
  68. RcVec3f pos = self.straightPath[i].pos;
  69. result.Add(new float3(-pos.x, pos.y, pos.z));
  70. }
  71. }
  72. }
  73. }