public static void Move(AOIEntity aoiEntity, Cell newCell, Cell preCell) { aoiEntity.Cell = newCell; preCell.Remove(aoiEntity); newCell.Add(aoiEntity); // 通知订阅该newCell Enter的Unit foreach (KeyValuePair <long, AOIEntity> kv in newCell.SubsEnterEntities) { if (kv.Value.SubEnterCells.Contains(preCell.Id)) { continue; } kv.Value.EnterSight(aoiEntity); } // 通知订阅preCell leave的Unit foreach (KeyValuePair <long, AOIEntity> kv in preCell.SubsLeaveEntities) { // 如果新的cell仍然在对方订阅的subleave中 if (kv.Value.SubLeaveCells.Contains(newCell.Id)) { continue; } kv.Value.LeaveSight(aoiEntity); } }
public static void CalcEnterAndLeaveCell(AOIEntity aoiEntity, int cellX, int cellY, HashSet <long> enterCell, HashSet <long> leaveCell) { enterCell.Clear(); leaveCell.Clear(); int r = (aoiEntity.ViewDistance - 1) / AOIManagerComponent.CellSize + 1; int leaveR = r; if (aoiEntity.Unit.Type == UnitType.Player) { leaveR += 1; } for (int i = cellX - leaveR; i <= cellX + leaveR; ++i) { for (int j = cellY - leaveR; j <= cellY + leaveR; ++j) { long cellId = CreateCellId(i, j); leaveCell.Add(cellId); if (i > cellX + r || i < cellX - r || j > cellY + r || j < cellY - r) { continue; } enterCell.Add(cellId); } } }
// leave离开self视野 public static void LeaveSight(this AOIEntity self, AOIEntity leave) { if (self.Id == leave.Id) { return; } if (!self.SeeUnits.ContainsKey(leave.Id)) { return; } self.SeeUnits.Remove(leave.Id); if (leave.Unit.Type == UnitType.Player) { self.SeePlayers.Remove(leave.Id); } leave.BeSeeUnits.Remove(self.Id); if (self.Unit.Type == UnitType.Player) { leave.BeSeePlayers.Remove(self.Id); } Game.EventSystem.Publish(new EventType.UnitLeaveSightRange { A = self, B = leave }); }
// cell中的unit进入self的视野 public static void SubEnter(this AOIEntity self, Cell cell) { cell.SubsEnterEntities.Add(self.Id, self); foreach (KeyValuePair <long, AOIEntity> kv in cell.AOIUnits) { if (kv.Key == self.Id) { continue; } self.EnterSight(kv.Value); } }
// cell中的unit离开self的视野 public static void UnSubLeave(this AOIEntity self, Cell cell) { foreach (KeyValuePair <long, AOIEntity> kv in cell.AOIUnits) { if (kv.Key == self.Id) { continue; } self.LeaveSight(kv.Value); } cell.SubsLeaveEntities.Remove(self.Id); }
// enter进入self视野 public static void EnterSight(this AOIEntity self, AOIEntity enter) { // 有可能之前在Enter,后来出了Enter还在LeaveCell,这样仍然没有删除,继续进来Enter,这种情况不需要处理 if (self.SeeUnits.ContainsKey(enter.Id)) { return; } if (!AOISeeCheckHelper.IsCanSee(self, enter)) { return; } if (self.Unit.Type == UnitType.Player) { if (enter.Unit.Type == UnitType.Player) { self.SeeUnits.Add(enter.Id, enter); enter.BeSeeUnits.Add(self.Id, self); self.SeePlayers.Add(enter.Id, enter); enter.BeSeePlayers.Add(self.Id, self); } else { self.SeeUnits.Add(enter.Id, enter); enter.BeSeeUnits.Add(self.Id, self); enter.BeSeePlayers.Add(self.Id, self); } } else { if (enter.Unit.Type == UnitType.Player) { self.SeeUnits.Add(enter.Id, enter); enter.BeSeeUnits.Add(self.Id, self); self.SeePlayers.Add(enter.Id, enter); } else { self.SeeUnits.Add(enter.Id, enter); enter.BeSeeUnits.Add(self.Id, self); } } Game.EventSystem.Publish(new EventType.UnitEnterSightRange() { A = self, B = enter }); }
public static void Remove(this AOIManagerComponent self, AOIEntity aoiEntity) { if (aoiEntity.Cell == null) { return; } // 通知订阅该Cell Leave的Unit aoiEntity.Cell.Remove(aoiEntity); foreach (KeyValuePair <long, AOIEntity> kv in aoiEntity.Cell.SubsLeaveEntities) { kv.Value.LeaveSight(aoiEntity); } // 通知自己订阅的Enter Cell,清理自己 foreach (long cellId in aoiEntity.SubEnterCells) { Cell cell = self.GetCell(cellId); aoiEntity.UnSubEnter(cell); } foreach (long cellId in aoiEntity.SubLeaveCells) { Cell cell = self.GetCell(cellId); aoiEntity.UnSubLeave(cell); } // 检查 if (aoiEntity.SeeUnits.Count > 1) { Log.Error($"aoiEntity has see units: {aoiEntity.SeeUnits.Count}"); } if (aoiEntity.BeSeeUnits.Count > 1) { Log.Error($"aoiEntity has beSee units: {aoiEntity.BeSeeUnits.Count}"); } }
public static void Add(this AOIManagerComponent self, AOIEntity aoiEntity, float x, float y) { int cellX = (int)(x * 1000) / AOIManagerComponent.CellSize; int cellY = (int)(y * 1000) / AOIManagerComponent.CellSize; if (aoiEntity.ViewDistance == 0) { aoiEntity.ViewDistance = 1; } AOIHelper.CalcEnterAndLeaveCell(aoiEntity, cellX, cellY, aoiEntity.SubEnterCells, aoiEntity.SubLeaveCells); // 遍历EnterCell foreach (long cellId in aoiEntity.SubEnterCells) { Cell cell = self.GetCell(cellId); aoiEntity.SubEnter(cell); } // 遍历LeaveCell foreach (long cellId in aoiEntity.SubLeaveCells) { Cell cell = self.GetCell(cellId); aoiEntity.SubLeave(cell); } // 自己加入的Cell Cell selfCell = self.GetCell(AOIHelper.CreateCellId(cellX, cellY)); aoiEntity.Cell = selfCell; selfCell.Add(aoiEntity); // 通知订阅该Cell Enter的Unit foreach (KeyValuePair <long, AOIEntity> kv in selfCell.SubsEnterEntities) { kv.Value.EnterSight(aoiEntity); } }
protected override async ETTask Run(EventType.ChangePosition args) { await ETTask.CompletedTask; Vector3 oldPos = args.OldPos; Unit unit = args.Unit; int oldCellX = (int)(oldPos.x * 1000) / AOIManagerComponent.CellSize; int oldCellY = (int)(oldPos.z * 1000) / AOIManagerComponent.CellSize; int newCellX = (int)(unit.Position.x * 1000) / AOIManagerComponent.CellSize; int newCellY = (int)(unit.Position.z * 1000) / AOIManagerComponent.CellSize; if (oldCellX == newCellX && oldCellY == newCellY) { return; } AOIEntity aoiEntity = unit.GetComponent <AOIEntity>(); if (aoiEntity == null) { return; } unit.Domain.GetComponent <AOIManagerComponent>().Move(aoiEntity, newCellX, newCellY); }
protected override void Run(object changePosition) { EventType.ChangePosition args = changePosition as EventType.ChangePosition; Vector3 oldPos = args.OldPos.Value; Unit unit = args.Unit; int oldCellX = (int)(oldPos.x * 1000) / AOIManagerComponent.CellSize; int oldCellY = (int)(oldPos.z * 1000) / AOIManagerComponent.CellSize; int newCellX = (int)(unit.Position.x * 1000) / AOIManagerComponent.CellSize; int newCellY = (int)(unit.Position.z * 1000) / AOIManagerComponent.CellSize; if (oldCellX == newCellX && oldCellY == newCellY) { return; } AOIEntity aoiEntity = unit.GetComponent <AOIEntity>(); if (aoiEntity == null) { return; } unit.Domain.GetComponent <AOIManagerComponent>().Move(aoiEntity, newCellX, newCellY); }
public static void Add(this Cell self, AOIEntity aoiEntity) { self.AOIUnits.Add(aoiEntity.Id, aoiEntity); }
public static void Remove(this Cell self, AOIEntity aoiEntity) { self.AOIUnits.Remove(aoiEntity.Id); }
/// <summary> /// 是否在Unit视野范围内 /// </summary> /// <param name="self"></param> /// <param name="unitId"></param> /// <returns></returns> public static bool IsBeSee(this AOIEntity self, long unitId) { return(self.BeSeePlayers.ContainsKey(unitId)); }
public static Dictionary <long, AOIEntity> GetSeePlayers(this AOIEntity self) { return(self.SeePlayers); }
public static void UnSubEnter(this AOIEntity self, Cell cell) { cell.SubsEnterEntities.Remove(self.Id); }
public static void SubLeave(this AOIEntity self, Cell cell) { cell.SubsLeaveEntities.Add(self.Id, self); }
public static void Move(this AOIManagerComponent self, AOIEntity aoiEntity, int cellX, int cellY) { long newCellId = AOIHelper.CreateCellId(cellX, cellY); if (aoiEntity.Cell.Id == newCellId) // cell没有变化 { return; } // 自己加入新的Cell Cell newCell = self.GetCell(newCellId); Move(aoiEntity, newCell, aoiEntity.Cell); AOIHelper.CalcEnterAndLeaveCell(aoiEntity, cellX, cellY, aoiEntity.enterHashSet, aoiEntity.leaveHashSet); // 算出自己leave新Cell foreach (long cellId in aoiEntity.leaveHashSet) { if (aoiEntity.SubLeaveCells.Contains(cellId)) { continue; } Cell cell = self.GetCell(cellId); aoiEntity.SubLeave(cell); } // 算出需要通知离开的Cell aoiEntity.SubLeaveCells.ExceptWith(aoiEntity.leaveHashSet); foreach (long cellId in aoiEntity.SubLeaveCells) { Cell cell = self.GetCell(cellId); aoiEntity.UnSubLeave(cell); } // 这里交换两个HashSet,提高性能 ObjectHelper.Swap(ref aoiEntity.SubLeaveCells, ref aoiEntity.leaveHashSet); // 算出自己看到的新Cell foreach (long cellId in aoiEntity.enterHashSet) { if (aoiEntity.SubEnterCells.Contains(cellId)) { continue; } Cell cell = self.GetCell(cellId); aoiEntity.SubEnter(cell); } // 离开的Enter aoiEntity.SubEnterCells.ExceptWith(aoiEntity.enterHashSet); foreach (long cellId in aoiEntity.SubEnterCells) { Cell cell = self.GetCell(cellId); aoiEntity.UnSubEnter(cell); } // 这里交换两个HashSet,提高性能 ObjectHelper.Swap(ref aoiEntity.SubEnterCells, ref aoiEntity.enterHashSet); }