Exemple #1
0
        /// <summary>
        /// 获取所有指定类型单位的碰撞器
        /// </summary>
        /// <param name="self"></param>
        /// <param name="types"></param>
        /// <param name="except"></param>
        /// <returns></returns>
        public static ListComponent <AOITriggerComponent> GetAllCollider(this AOICell self, List <UnitType> types, AOITriggerComponent except)
        {
            var res = ListComponent <AOITriggerComponent> .Create();

            if (self.IsDisposed)
            {
                return(res);
            }
            var isAll = types.Contains(UnitType.ALL);

            for (int i = self.Triggers.Count - 1; i >= 0; i--)
            {
                var item = self.Triggers[i];
                if (item.IsDisposed)
                {
                    self.Triggers.RemoveAt(i);
                    Log.Warning("自动移除不成功");
                    continue;
                }
                if (!item.IsCollider || item == except)
                {
                    continue;
                }

                if (isAll || types.Contains(item.GetParent <AOIUnitComponent>().Type))
                {
                    // Log.Info("GetAllUnit key:"+item.Key);
                    res.Add(item);
                }
            }
            return(res);
        }
Exemple #2
0
        /// <summary>
        /// 移动一个 AOI 对象, 设置新的 (2D / 3D) 坐标
        /// </summary>
        /// <param name="self"></param>
        /// <param name="position"></param>
        public static void Move(this AOIUnitComponent self, Vector3 position)
        {
            var oldpos = self.Position;

            self.Position = position;
            AOICell cell    = self.Scene.GetAOIGrid(position);
            var     oldgrid = self.Cell;

            if (cell != oldgrid)//跨格子了:AOI刷新
            {
                self.ChangeTo(cell);
            }
            //触发器刷新 自己进入或离开别人的
            if (self.Collider != null)
            {
                self.Collider.AfterChangeBroadcastToOther(self.Collider.GetRealPos(oldpos), self.Collider.GetRealRot());
            }

            //触发器刷新 别人进入或离开自己的
            for (int i = 0; i < self.SphereTriggers.Count; i++)
            {
                var item = self.SphereTriggers[i];
                item.AfterChangePosition(item.GetRealPos(oldpos));
            }
        }
        /// <summary>
        /// 注册一个 AOI 对象, 同时设置其默认 AOI 半径。注:每个对象都有一个默认的 AOI 半径,凡第一次进入半径范围的其它物体,都会触发 AOI 消息。
        /// </summary>
        /// <param name="self"></param>
        /// <param name="unit"></param>
        public static void RegisterUnit(this AOISceneComponent self, AOIUnitComponent unit)
        {
            unit.Scene = self;
            AOICell cell = self.GetAOIGrid(unit.Position);

            cell.Add(unit);
            Log.Info("RegisterUnit:" + unit.Id + "  Position:" + unit.Position + "  grid x:" + cell.posx + ",y:" + cell.posy + " type" + unit.Type + " range" + unit.Range);

            using (var ListenerGrids = cell.GetNearbyGrid(unit.Range))
            {
                for (int i = 0; i < ListenerGrids.Count; i++)
                {
                    var item = ListenerGrids[i];
                    item.AddListener(unit);
                    if (unit.Type == UnitType.Player)
                    {
                        using (var list = item.GetAllUnit())
                        {
                            for (int j = 0; j < list.Count; j++)
                            {
                                var t = list[j];
                                Game.EventSystem.Publish(new AOIRegisterUnit()
                                {
                                    Receive = unit,
                                    Unit    = t
                                });
                            }
                        }
                    }
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// 获取自身为中心指定圈数的所有格子
        /// </summary>
        /// <param name="self"></param>
        /// <param name="turnNum">圈数</param>
        /// <returns></returns>
        public static ListComponent <AOICell> GetNearbyGrid(this AOICell self, int turnNum)
        {
            var scene = self.DomainScene().GetComponent <AOISceneComponent>();

            if (scene == null)
            {
                return(ListComponent <AOICell> .Create());
            }
            return(scene.GetNearbyGrid(turnNum, self.posx, self.posy));
        }
Exemple #5
0
 /// <summary>
 /// 获取与碰撞器的关系:-1无关 0相交或包括碰撞器 1在碰撞器内部
 /// </summary>
 /// <param name="self"></param>
 /// <param name="trigger"></param>
 /// <param name="position"></param>
 /// <param name="rotation"></param>
 /// <returns></returns>
 public static int GetRelationshipWithTrigger(this AOICell self, AOITriggerComponent trigger, Vector3 position, Quaternion rotation)
 {
     if (trigger.TriggerType == TriggerShapeType.Cube)
     {
         var obb = trigger.GetComponent <OBBComponent>();
         return(AOIHelper.GetGridRelationshipWithOBB(position, rotation, obb.Scale, self.xMax - self.xMin, self.posx, self.posy));
     }
     else
     {
         return(AOIHelper.GetGridRelationshipWithSphere(position, trigger.Radius, self.xMax - self.xMin, self.posx, self.posy));
     }
 }
Exemple #6
0
        /// <summary>
        /// 获取自身为中心指定圈数的所有格子的所有指定类型单位
        /// </summary>
        /// <param name="self"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static ListComponent <AOIUnitComponent> GetNearbyUnit(this AOICell self, int turnNum, UnitType type = UnitType.ALL)
        {
            var grid = self.GetNearbyGrid(turnNum);

            if (grid != null)
            {
                var res = grid.GetAllUnit(type);
                grid.Dispose();
                return(res);
            }
            return(ListComponent <AOIUnitComponent> .Create());
        }
Exemple #7
0
 /// <summary>
 /// 添加触发器监视
 /// </summary>
 /// <param name="self"></param>
 /// <param name="trigger"></param>
 /// <returns></returns>
 public static void AddTriggerListener(this AOICell self, AOITriggerComponent trigger)
 {
     if (Define.Debug)
     {
         if (!trigger.DebugMap.ContainsKey(self))
         {
             trigger.DebugMap[self] = 0;
         }
         trigger.DebugMap[self]++;
         trigger.LogInfo.Add("AddTriggerListener " + self.posx + "," + self.posy + "  " + trigger.GetRealPos() + "  " +
                             DateTime.Now.ToString("HH:mm:ss fff:ffffff") + "\r\n" + new StackTrace());
     }
     trigger.FollowCell.Add(self);
     self.Triggers.Add(trigger);
 }
Exemple #8
0
        /// <summary>
        /// 获取所有指定类型单位
        /// </summary>
        /// <param name="self"></param>
        /// <param name="types"></param>
        /// <returns></returns>
        public static ListComponent <AOIUnitComponent> GetAllUnit(this AOICell self, List <UnitType> types)
        {
            var res = ListComponent <AOIUnitComponent> .Create();

            var isAll = types.Contains(UnitType.ALL);

            foreach (var item in self.idUnits)
            {
                if (types.Contains(item.Key) || isAll)
                {
                    // Log.Info("GetAllUnit key:"+item.Key);
                    res.AddRange(item.Value);
                }
            }
            return(res);
        }
Exemple #9
0
        /// <summary>
        /// 获取所有指定类型单位
        /// </summary>
        /// <param name="self"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static ListComponent <AOIUnitComponent> GetAllUnit(this AOICell self, UnitType type = UnitType.ALL)
        {
            var res = ListComponent <AOIUnitComponent> .Create();

            if (type == UnitType.ALL)
            {
                foreach (var item in self.idUnits)
                {
                    res.AddRange(item.Value);
                }
            }
            else if (self.idUnits.ContainsKey(type))
            {
                res.AddRange(self.idUnits[type]);
            }
            return(res);
        }
        private static AOICell GetCell(this AOISceneComponent self, int x, int y, bool create = true)
        {
            long    cellId = AOIHelper.CreateCellId(x, y);
            AOICell cell   = self.GetChild <AOICell>(cellId);

            if (cell == null && create)
            {
                cell              = self.AddChildWithId <AOICell>(cellId);
                cell.xMin         = x * self.gridLen;
                cell.xMax         = cell.xMin + self.gridLen;
                cell.yMin         = y * self.gridLen;
                cell.yMax         = cell.yMin + self.gridLen;
                cell.posx         = x;
                cell.posy         = y;
                cell.halfDiagonal = self.halfDiagonal;
            }

            return(cell);
        }
Exemple #11
0
 /// <summary>
 /// 进入格子
 /// </summary>
 /// <param name="self"></param>
 /// <param name="unit"></param>
 public static void Add(this AOICell self, AOIUnitComponent unit)
 {
     unit.Cell = self;
     if (Define.Debug && self.idUnits[unit.Type].Contains(unit))//Debug开启检测
     {
         Log.Error("self.idUnits[unit.Type].Contains(unit)");
     }
     self.idUnits[unit.Type].Add(unit);
     for (int i = 0; i < self.ListenerUnits.Count; i++)
     {
         var item = self.ListenerUnits[i];
         if (item.Type == UnitType.Player)
         {
             Game.EventSystem.Publish(new EventType.AOIRegisterUnit()
             {
                 Receive = item,
                 Unit    = unit
             });
         }
     }
 }
Exemple #12
0
 private static void RaycastHits(Ray ray, AOICell cell, Vector3 inPoint, ListComponent <RaycastHit> hits,
                                 HashSetComponent <AOITriggerComponent> triggers, DictionaryComponent <UnitType, bool> type)
 {
     for (int i = cell.Triggers.Count - 1; i >= 0; i--)
     {
         var item = cell.Triggers[i];
         if (item.IsDisposed)
         {
             cell.Triggers.RemoveAt(i);
             Log.Warning("自动移除不成功");
             continue;
         }
         if (item.IsCollider && !triggers.Contains(item) && type.ContainsKey(UnitType.ALL) ||
             type.ContainsKey(item.GetParent <AOIUnitComponent>().Type))
         {
             if (item.IsPointInTrigger(inPoint, item.GetRealPos(), item.GetRealRot()))
             {
                 triggers.Add(item);
                 hits.Add(new RaycastHit
                 {
                     Hit      = inPoint,
                     Trigger  = item,
                     Distance = Vector3.Distance(inPoint, ray.Start)
                 });
             }
             else if (item.IsRayInTrigger(ray, item.GetRealPos(), item.GetRealRot(), out var hit))
             {
                 triggers.Add(item);
                 hits.Add(new RaycastHit
                 {
                     Hit      = hit,
                     Trigger  = item,
                     Distance = Vector3.Distance(hit, ray.Start)
                 });
             }
         }
     }
 }
Exemple #13
0
 /// <summary>
 /// 离开
 /// </summary>
 /// <param name="self"></param>
 /// <param name="unit"></param>
 public static void Remove(this AOICell self, AOIUnitComponent unit)
 {
     if (self == null || self.IsDisposed)
     {
         return;
     }
     if (self.idUnits.ContainsKey(unit.Type))
     {
         for (int i = 0; i < self.ListenerUnits.Count; i++)
         {
             var item = self.ListenerUnits[i];
             if (item.Type == UnitType.Player)
             {
                 Game.EventSystem.Publish(new EventType.AOIRemoveUnit()
                 {
                     Receive = item,
                     Unit    = unit
                 });
             }
         }
         self.idUnits[unit.Type].Remove(unit);
         unit.Cell = null;
     }
 }
Exemple #14
0
 /// <summary>
 /// 移除监视
 /// </summary>
 /// <param name="self"></param>
 /// <param name="unit"></param>
 /// <returns></returns>
 public static void RemoveListener(this AOICell self, AOIUnitComponent unit)
 {
     // Log.Info("RemoveListener"+unit.Id+" "+self.posx+","+self.posy);
     self.ListenerUnits.Remove(unit);
 }
Exemple #15
0
        public static bool Raycast(AOISceneComponent scene, Ray ray, out RaycastHit hit, UnitType[] type = null)
        {
            hit = default;
            if (type == null)
            {
                return(false);
            }
            using (DictionaryComponent <UnitType, bool> typeTemp = DictionaryComponent <UnitType, bool> .Create())
            {
                using (HashSetComponent <AOITriggerComponent> temp = HashSetComponent <AOITriggerComponent> .Create())
                {
                    for (int i = 0; i < type.Length; i++)
                    {
                        var item = type[i];
                        typeTemp.Add(item, true);
                    }
                    int xIndex = (int)Math.Floor(ray.Start.x / scene.gridLen);
                    int yIndex = (int)Math.Floor(ray.Start.z / scene.gridLen);
                    //z = kx+b
                    float k   = 0;
                    float k_1 = 0;
                    float b   = 0;
                    if (ray.Dir.x != 0 && ray.Dir.z != 0)
                    {
                        k   = ray.Dir.z / ray.Dir.x;
                        k_1 = ray.Dir.x / ray.Dir.z;
                        b   = ray.Start.z - k * ray.Start.x;
                    }

                    Vector3 inPoint = ray.Start;
                    while (true)
                    {
                        long    cellId = AOIHelper.CreateCellId(xIndex, yIndex);
                        AOICell cell   = scene.GetChild <AOICell>(cellId);
                        var     xMin   = xIndex * scene.gridLen;
                        var     xMax   = xMin + scene.gridLen;
                        var     yMin   = yIndex * scene.gridLen;
                        var     yMax   = yMin + scene.gridLen;
                        //Log.Info("Raycast Check "+xIndex+" "+yIndex);
                        if (cell != null)
                        {
                            ListComponent <RaycastHit> hits = ListComponent <RaycastHit> .Create();

                            RaycastHits(ray, cell, inPoint, hits, temp, typeTemp);
                            if (hits.Count > 0)
                            {
                                hits.KSsort((i1, i2) => i1.Distance >= i2.Distance?1:-1);//从小到大
                                hit = hits[0];
                                //Log.Info("hits.Count > 0"+hit.Trigger.Parent.Parent.Id);
                                hits.Dispose();
                                return(true);
                            }
                        }
                        //一般情况
                        if (ray.Dir.x != 0 && ray.Dir.z != 0)
                        {
                            if (ray.Dir.x > 0 && ray.Dir.z > 0)
                            {
                                var z1 = xMax * k + b;
                                if (z1 > yMin && z1 < yMax)
                                {
                                    xIndex++;
                                    inPoint = new Vector3(xMax, inPoint.y + (xMax - inPoint.x) * ray.Dir.y / ray.Dir.x, z1);
                                }
                                else
                                {
                                    yIndex++;
                                    inPoint = new Vector3((yMax - b) * k_1, inPoint.y + (yMax - inPoint.z) * ray.Dir.y / ray.Dir.z, yMax);
                                }
                            }
                            else if (ray.Dir.x > 0 && ray.Dir.z < 0)
                            {
                                var z1 = xMax * k + b;
                                if (z1 > yMin && z1 < yMax)
                                {
                                    xIndex++;
                                    inPoint = new Vector3(xMax, inPoint.y + (xMax - inPoint.x) * ray.Dir.y / ray.Dir.x, z1);
                                }
                                else
                                {
                                    yIndex--;
                                    inPoint = new Vector3((yMin - b) * k_1, inPoint.y + (yMin - inPoint.z) * ray.Dir.y / ray.Dir.z, yMin);
                                }
                            }
                            else if (ray.Dir.x < 0 && ray.Dir.z < 0)
                            {
                                var z1 = xMin * k + b;
                                if (z1 > yMin && z1 < yMax)
                                {
                                    xIndex--;
                                    inPoint = new Vector3(xMin, inPoint.y + (xMin - inPoint.x) * ray.Dir.y / ray.Dir.x, z1);
                                }
                                else
                                {
                                    yIndex--;
                                    inPoint = new Vector3((yMin - b) * k_1, inPoint.y + (yMin - inPoint.z) * ray.Dir.y / ray.Dir.z, yMin);
                                }
                            }
                            else if (ray.Dir.x < 0 && ray.Dir.z > 0)
                            {
                                var z1 = xMin * k + b;
                                if (z1 > yMin && z1 < yMax)
                                {
                                    xIndex--;
                                    inPoint = new Vector3(xMin, inPoint.y + (xMin - inPoint.x) * ray.Dir.y / ray.Dir.x, z1);
                                }
                                else
                                {
                                    yIndex++;
                                    inPoint = new Vector3((yMax - b) * k_1, inPoint.y + (yMax - inPoint.z) * ray.Dir.y / ray.Dir.z, yMax);
                                }
                            }
                            else
                            {
                                Log.Error("What's f**k???");
                            }
                        }
                        //平行于轴了
                        else if (ray.Dir.x == 0 && ray.Dir.z != 0)
                        {
                            if (ray.Dir.z > 0)
                            {
                                yIndex++;
                                inPoint = new Vector3(inPoint.x, inPoint.y + (yMax - inPoint.z) * ray.Dir.y / ray.Dir.z, yMax);
                            }
                            else
                            {
                                yIndex--;
                                inPoint = new Vector3(inPoint.x, inPoint.y + (yMin - inPoint.z) * ray.Dir.y / ray.Dir.z, yMin);
                            }
                        }
                        else if (ray.Dir.z == 0 && ray.Dir.x != 0)
                        {
                            if (ray.Dir.x > 0)
                            {
                                xIndex++;
                                inPoint = new Vector3(xMax, inPoint.y + (xMax - inPoint.x) * ray.Dir.y / ray.Dir.x, inPoint.z);
                            }
                            else
                            {
                                xIndex--;
                                inPoint = new Vector3(xMin, inPoint.y + (xMin - inPoint.x) * ray.Dir.y / ray.Dir.x, inPoint.z);
                            }
                        }
                        //垂直于地图
                        else
                        {
                            break;
                        }
                        if (Vector3.Distance(inPoint, ray.Start) > ray.Distance)
                        {
                            break;
                        }
                    }
                }
            }
            return(false);
        }
Exemple #16
0
        /// <summary>
        /// 改变格子
        /// </summary>
        /// <param name="self"></param>
        /// <param name="newgrid"></param>
        public static void ChangeTo(this AOIUnitComponent self, AOICell newgrid)
        {
            AOICell oldgrid = self.Cell;

            Log.Info(self.Id + "From: " + "  grid x:" + oldgrid.posx + ",y:" + oldgrid.posy + "  ChangeTo:grid x:" + newgrid.posx + ",y:" + newgrid.posy);
            #region 广播给别人
            using (DictionaryComponent <AOIUnitComponent, int> dic = DictionaryComponent <AOIUnitComponent, int> .Create())
            {
                //Remove
                if (oldgrid.idUnits.ContainsKey(self.Type))
                {
                    for (int i = 0; i < oldgrid.ListenerUnits.Count; i++)
                    {
                        var item = oldgrid.ListenerUnits[i];
                        if (item.Type == UnitType.Player && item != self)
                        {
                            dic.Add(item, -1);
                        }
                    }

                    oldgrid.idUnits[self.Type].Remove(self);
                    self.Cell = null;
                }
                else
                {
                    Log.Error("unit.Type=" + self.Type + "未添加就删除");
                }

                //Add
                self.Cell = newgrid;
                if (Define.Debug && newgrid.idUnits[self.Type].Contains(self))
                {
                    Log.Error("newgrid.idUnits[self.Type].Contains(self)");
                }
                newgrid.idUnits[self.Type].Add(self);
                for (int i = 0; i < newgrid.ListenerUnits.Count; i++)
                {
                    var item = newgrid.ListenerUnits[i];
                    if (item.Type == UnitType.Player && item != self)
                    {
                        if (dic.ContainsKey(item))
                        {
                            dic[item] += 1;
                        }
                        else
                        {
                            dic.Add(item, 1);
                        }
                    }
                }

                foreach (var item in dic)
                {
                    if (item.Value > 0)
                    {
                        Game.EventSystem.Publish(new EventType.AOIRegisterUnit()
                        {
                            Receive = item.Key,
                            Unit    = self,
                        });
                    }
                    else if (item.Value < 0)
                    {
                        Game.EventSystem.Publish(new EventType.AOIRemoveUnit()
                        {
                            Receive = item.Key,
                            Unit    = self
                        });
                    }
                }
            }
            #endregion

            #region 广播给自己 && 刷新监听
            var older = oldgrid.GetNearbyGrid(self.Range);
            var newer = newgrid.GetNearbyGrid(self.Range);
            DictionaryComponent <AOICell, int> temp = DictionaryComponent <AOICell, int> .Create();

            for (int i = 0; i < older.Count; i++)
            {
                var item = older[i];
                temp[item] = -1;
            }
            for (int i = 0; i < newer.Count; i++)
            {
                var item = newer[i];
                if (temp.ContainsKey(item))
                {
                    temp[item] = 0;
                }
                else
                {
                    temp[item] = 1;
                }
            }
            ListComponent <AOIUnitComponent> adder = ListComponent <AOIUnitComponent> .Create();

            ListComponent <AOIUnitComponent> remover = ListComponent <AOIUnitComponent> .Create();

            foreach (var item in temp)
            {
                if (item.Value > 0)
                {
                    item.Key.AddListener(self);
                    adder.AddRange(item.Key.GetAllUnit());
                }
                else if (item.Value < 0)
                {
                    item.Key.RemoveListener(self);
                    remover.AddRange(item.Key.GetAllUnit());
                }
            }
            if (self.Type == UnitType.Player)
            {
                for (int i = 0; i < adder.Count; i++)
                {
                    var item = adder[i];
                    if (item == self)
                    {
                        continue;
                    }
                    Log.Info("AOIRegisterUnit" + item.Id);
                    Game.EventSystem.Publish(new EventType.AOIRegisterUnit
                    {
                        Receive = self,
                        Unit    = item
                    });
                }
                for (int i = 0; i < remover.Count; i++)
                {
                    var item = remover[i];
                    if (item == self)
                    {
                        continue;
                    }
                    Log.Info("AOIRemoveUnit" + item.Id);
                    Game.EventSystem.Publish(new EventType.AOIRemoveUnit()
                    {
                        Receive = self,
                        Unit    = item
                    });
                }
            }
            temp.Dispose();
            newer.Dispose();
            older.Dispose();
            adder.Dispose();
            remover.Dispose();
            #endregion
        }