예제 #1
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);
        }
예제 #2
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
        }