AOIManagerComponentSystem.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. using System.Collections.Generic;
  2. namespace ET.Server
  3. {
  4. [FriendOf(typeof(AOIManagerComponent))]
  5. [FriendOf(typeof(AOIEntity))]
  6. [FriendOf(typeof(Cell))]
  7. public static class AOIManagerComponentSystem
  8. {
  9. public static void Add(this AOIManagerComponent self, AOIEntity aoiEntity, float x, float y)
  10. {
  11. int cellX = (int)(x * 1000) / AOIManagerComponent.CellSize;
  12. int cellY = (int)(y * 1000) / AOIManagerComponent.CellSize;
  13. if (aoiEntity.ViewDistance == 0)
  14. {
  15. aoiEntity.ViewDistance = 1;
  16. }
  17. AOIHelper.CalcEnterAndLeaveCell(aoiEntity, cellX, cellY, aoiEntity.SubEnterCells, aoiEntity.SubLeaveCells);
  18. // 遍历EnterCell
  19. foreach (long cellId in aoiEntity.SubEnterCells)
  20. {
  21. Cell cell = self.GetCell(cellId);
  22. aoiEntity.SubEnter(cell);
  23. }
  24. // 遍历LeaveCell
  25. foreach (long cellId in aoiEntity.SubLeaveCells)
  26. {
  27. Cell cell = self.GetCell(cellId);
  28. aoiEntity.SubLeave(cell);
  29. }
  30. // 自己加入的Cell
  31. Cell selfCell = self.GetCell(AOIHelper.CreateCellId(cellX, cellY));
  32. aoiEntity.Cell = selfCell;
  33. selfCell.Add(aoiEntity);
  34. // 通知订阅该Cell Enter的Unit
  35. foreach (KeyValuePair<long, AOIEntity> kv in selfCell.SubsEnterEntities)
  36. {
  37. kv.Value.EnterSight(aoiEntity);
  38. }
  39. }
  40. public static void Remove(this AOIManagerComponent self, AOIEntity aoiEntity)
  41. {
  42. if (aoiEntity.Cell == null)
  43. {
  44. return;
  45. }
  46. // 通知订阅该Cell Leave的Unit
  47. aoiEntity.Cell.Remove(aoiEntity);
  48. foreach (KeyValuePair<long, AOIEntity> kv in aoiEntity.Cell.SubsLeaveEntities)
  49. {
  50. kv.Value.LeaveSight(aoiEntity);
  51. }
  52. // 通知自己订阅的Enter Cell,清理自己
  53. foreach (long cellId in aoiEntity.SubEnterCells)
  54. {
  55. Cell cell = self.GetCell(cellId);
  56. aoiEntity.UnSubEnter(cell);
  57. }
  58. foreach (long cellId in aoiEntity.SubLeaveCells)
  59. {
  60. Cell cell = self.GetCell(cellId);
  61. aoiEntity.UnSubLeave(cell);
  62. }
  63. // 检查
  64. if (aoiEntity.SeeUnits.Count > 1)
  65. {
  66. Log.Error($"aoiEntity has see units: {aoiEntity.SeeUnits.Count}");
  67. }
  68. if (aoiEntity.BeSeeUnits.Count > 1)
  69. {
  70. Log.Error($"aoiEntity has beSee units: {aoiEntity.BeSeeUnits.Count}");
  71. }
  72. }
  73. private static Cell GetCell(this AOIManagerComponent self, long cellId)
  74. {
  75. Cell cell = self.GetChild<Cell>(cellId);
  76. if (cell == null)
  77. {
  78. cell = self.AddChildWithId<Cell>(cellId);
  79. }
  80. return cell;
  81. }
  82. public static void Move(AOIEntity aoiEntity, Cell newCell, Cell preCell)
  83. {
  84. aoiEntity.Cell = newCell;
  85. preCell.Remove(aoiEntity);
  86. newCell.Add(aoiEntity);
  87. // 通知订阅该newCell Enter的Unit
  88. foreach (KeyValuePair<long, AOIEntity> kv in newCell.SubsEnterEntities)
  89. {
  90. if (kv.Value.SubEnterCells.Contains(preCell.Id))
  91. {
  92. continue;
  93. }
  94. kv.Value.EnterSight(aoiEntity);
  95. }
  96. // 通知订阅preCell leave的Unit
  97. foreach (KeyValuePair<long, AOIEntity> kv in preCell.SubsLeaveEntities)
  98. {
  99. // 如果新的cell仍然在对方订阅的subleave中
  100. if (kv.Value.SubLeaveCells.Contains(newCell.Id))
  101. {
  102. continue;
  103. }
  104. kv.Value.LeaveSight(aoiEntity);
  105. }
  106. }
  107. public static void Move(this AOIManagerComponent self, AOIEntity aoiEntity, int cellX, int cellY)
  108. {
  109. long newCellId = AOIHelper.CreateCellId(cellX, cellY);
  110. if (aoiEntity.Cell.Id == newCellId) // cell没有变化
  111. {
  112. return;
  113. }
  114. // 自己加入新的Cell
  115. Cell newCell = self.GetCell(newCellId);
  116. Move(aoiEntity, newCell, aoiEntity.Cell);
  117. AOIHelper.CalcEnterAndLeaveCell(aoiEntity, cellX, cellY, aoiEntity.enterHashSet, aoiEntity.leaveHashSet);
  118. // 算出自己leave新Cell
  119. foreach (long cellId in aoiEntity.leaveHashSet)
  120. {
  121. if (aoiEntity.SubLeaveCells.Contains(cellId))
  122. {
  123. continue;
  124. }
  125. Cell cell = self.GetCell(cellId);
  126. aoiEntity.SubLeave(cell);
  127. }
  128. // 算出需要通知离开的Cell
  129. aoiEntity.SubLeaveCells.ExceptWith(aoiEntity.leaveHashSet);
  130. foreach (long cellId in aoiEntity.SubLeaveCells)
  131. {
  132. Cell cell = self.GetCell(cellId);
  133. aoiEntity.UnSubLeave(cell);
  134. }
  135. // 这里交换两个HashSet,提高性能
  136. ObjectHelper.Swap(ref aoiEntity.SubLeaveCells, ref aoiEntity.leaveHashSet);
  137. // 算出自己看到的新Cell
  138. foreach (long cellId in aoiEntity.enterHashSet)
  139. {
  140. if (aoiEntity.SubEnterCells.Contains(cellId))
  141. {
  142. continue;
  143. }
  144. Cell cell = self.GetCell(cellId);
  145. aoiEntity.SubEnter(cell);
  146. }
  147. // 离开的Enter
  148. aoiEntity.SubEnterCells.ExceptWith(aoiEntity.enterHashSet);
  149. foreach (long cellId in aoiEntity.SubEnterCells)
  150. {
  151. Cell cell = self.GetCell(cellId);
  152. aoiEntity.UnSubEnter(cell);
  153. }
  154. // 这里交换两个HashSet,提高性能
  155. ObjectHelper.Swap(ref aoiEntity.SubEnterCells, ref aoiEntity.enterHashSet);
  156. }
  157. }
  158. }