AOIManagerComponentSystem.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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 partial 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, EntityRef<AOIEntity>> kv in selfCell.SubsEnterEntities)
  36. {
  37. AOIEntity e = kv.Value;
  38. e.EnterSight(aoiEntity);
  39. }
  40. }
  41. public static void Remove(this AOIManagerComponent self, AOIEntity aoiEntity)
  42. {
  43. if (aoiEntity.Cell == null)
  44. {
  45. return;
  46. }
  47. // 通知订阅该Cell Leave的Unit
  48. aoiEntity.Cell.Remove(aoiEntity);
  49. foreach (KeyValuePair<long, EntityRef<AOIEntity>> kv in aoiEntity.Cell.SubsLeaveEntities)
  50. {
  51. AOIEntity e = kv.Value;
  52. e?.LeaveSight(aoiEntity);
  53. }
  54. // 通知自己订阅的Enter Cell,清理自己
  55. foreach (long cellId in aoiEntity.SubEnterCells)
  56. {
  57. Cell cell = self.GetCell(cellId);
  58. aoiEntity.UnSubEnter(cell);
  59. }
  60. foreach (long cellId in aoiEntity.SubLeaveCells)
  61. {
  62. Cell cell = self.GetCell(cellId);
  63. aoiEntity.UnSubLeave(cell);
  64. }
  65. // 检查
  66. if (aoiEntity.SeeUnits.Count > 1)
  67. {
  68. Log.Error($"aoiEntity has see units: {aoiEntity.SeeUnits.Count}");
  69. }
  70. if (aoiEntity.BeSeeUnits.Count > 1)
  71. {
  72. Log.Error($"aoiEntity has beSee units: {aoiEntity.BeSeeUnits.Count}");
  73. }
  74. }
  75. private static Cell GetCell(this AOIManagerComponent self, long cellId)
  76. {
  77. Cell cell = self.GetChild<Cell>(cellId);
  78. if (cell == null)
  79. {
  80. cell = self.AddChildWithId<Cell>(cellId);
  81. }
  82. return cell;
  83. }
  84. public static void Move(AOIEntity aoiEntity, Cell newCell, Cell preCell)
  85. {
  86. aoiEntity.Cell = newCell;
  87. preCell.Remove(aoiEntity);
  88. newCell.Add(aoiEntity);
  89. // 通知订阅该newCell Enter的Unit
  90. foreach (KeyValuePair<long, EntityRef<AOIEntity>> kv in newCell.SubsEnterEntities)
  91. {
  92. AOIEntity e = kv.Value;
  93. if (e.SubEnterCells.Contains(preCell.Id))
  94. {
  95. continue;
  96. }
  97. e.EnterSight(aoiEntity);
  98. }
  99. // 通知订阅preCell leave的Unit
  100. foreach (KeyValuePair<long, EntityRef<AOIEntity>> kv in preCell.SubsLeaveEntities)
  101. {
  102. // 如果新的cell仍然在对方订阅的subleave中
  103. AOIEntity e = kv.Value;
  104. if (e.SubLeaveCells.Contains(newCell.Id))
  105. {
  106. continue;
  107. }
  108. e.LeaveSight(aoiEntity);
  109. }
  110. }
  111. public static void Move(this AOIManagerComponent self, AOIEntity aoiEntity, int cellX, int cellY)
  112. {
  113. long newCellId = AOIHelper.CreateCellId(cellX, cellY);
  114. if (aoiEntity.Cell.Id == newCellId) // cell没有变化
  115. {
  116. return;
  117. }
  118. // 自己加入新的Cell
  119. Cell newCell = self.GetCell(newCellId);
  120. Move(aoiEntity, newCell, aoiEntity.Cell);
  121. AOIHelper.CalcEnterAndLeaveCell(aoiEntity, cellX, cellY, aoiEntity.enterHashSet, aoiEntity.leaveHashSet);
  122. // 算出自己leave新Cell
  123. foreach (long cellId in aoiEntity.leaveHashSet)
  124. {
  125. if (aoiEntity.SubLeaveCells.Contains(cellId))
  126. {
  127. continue;
  128. }
  129. Cell cell = self.GetCell(cellId);
  130. aoiEntity.SubLeave(cell);
  131. }
  132. // 算出需要通知离开的Cell
  133. aoiEntity.SubLeaveCells.ExceptWith(aoiEntity.leaveHashSet);
  134. foreach (long cellId in aoiEntity.SubLeaveCells)
  135. {
  136. Cell cell = self.GetCell(cellId);
  137. aoiEntity.UnSubLeave(cell);
  138. }
  139. // 这里交换两个HashSet,提高性能
  140. ObjectHelper.Swap(ref aoiEntity.SubLeaveCells, ref aoiEntity.leaveHashSet);
  141. // 算出自己看到的新Cell
  142. foreach (long cellId in aoiEntity.enterHashSet)
  143. {
  144. if (aoiEntity.SubEnterCells.Contains(cellId))
  145. {
  146. continue;
  147. }
  148. Cell cell = self.GetCell(cellId);
  149. aoiEntity.SubEnter(cell);
  150. }
  151. // 离开的Enter
  152. aoiEntity.SubEnterCells.ExceptWith(aoiEntity.enterHashSet);
  153. foreach (long cellId in aoiEntity.SubEnterCells)
  154. {
  155. Cell cell = self.GetCell(cellId);
  156. aoiEntity.UnSubEnter(cell);
  157. }
  158. // 这里交换两个HashSet,提高性能
  159. ObjectHelper.Swap(ref aoiEntity.SubEnterCells, ref aoiEntity.enterHashSet);
  160. }
  161. }
  162. }