Exemplo n.º 1
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));
     }
 }
Exemplo n.º 2
0
        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);
        }
Exemplo n.º 3
0
        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);
            }
        }
Exemplo n.º 4
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);
        }
Exemplo n.º 5
0
        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);
        }
Exemplo n.º 6
0
        /// <summary>
        /// 改变格子
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="viewLen"></param>
        public static async ETTask ChangeGrid(this AOISceneViewComponent self, int x, int y, int viewLen)
        {
            CoroutineLock coroutineLock = null;

            try
            {
                coroutineLock = await CoroutineLockComponent.Instance.Wait(CoroutineLockType.AOIView, self.GetHashCode());

                while (SceneManagerComponent.Instance.Busing)
                {
                    await TimerComponent.Instance.WaitAsync(1);
                }
                if (self.LastGridX != null)
                {
                    int count = 0;
                    count += Math.Abs(x - (int)self.LastGridX);
                    count += Math.Abs(y - (int)self.LastGridY);
                    if (count > 4) //太远了走loading
                    {
                        self.ChangeToScene().Coroutine();
                    }
                }

                DictionaryComponent <long, int> temp = DictionaryComponent <long, int> .Create();

                for (int i = -viewLen; i <= viewLen; i++)
                {
                    for (int j = -viewLen; j <= viewLen; j++)
                    {
                        if (self.LastGridY != null)
                        {
                            var oldid = AOIHelper.CreateCellId((int)self.LastGridX + i, (int)self.LastGridY + j);
                            if (!temp.ContainsKey(oldid))
                            {
                                temp[oldid] = 0;
                            }

                            temp[oldid]--;
                        }

                        var newid = AOIHelper.CreateCellId(x + i, y + j);
                        if (!temp.ContainsKey(newid))
                        {
                            temp[newid] = 0;
                        }

                        temp[newid]++;
                    }
                }

                foreach (var item in temp)
                {
                    if (item.Value == 0)
                    {
                        continue;
                    }
                    var objs = self.DynamicSceneMap[self.CurMap].GridMapObjects;
                    if (!objs.ContainsKey(item.Key))
                    {
                        continue;
                    }
                    for (int i = 0; i < objs[item.Key].Count; i++)
                    {
                        var obj = objs[item.Key][i];
                        if (item.Value > 0) //新增
                        {
                            if (self.DynamicSceneObjectMapCount.ContainsKey(obj))
                            {
                                self.DynamicSceneObjectMapCount[obj]++;
                            }
                            else
                            {
                                self.DynamicSceneObjectMapCount[obj] = 1;
                            }

                            //需要显示
                            if (self.DynamicSceneObjectMapCount[obj] > 0)
                            {
                                AOISceneViewComponent.DynamicSceneViewObj viewObj;
                                //已经有
                                if (self.DynamicSceneObjectMapObj.ContainsKey(obj))
                                {
                                    viewObj = self.DynamicSceneObjectMapObj[obj];
                                    if (viewObj.Obj == null) //之前有单没加载出来,IsLoading改为true,防止之前已经被改成false了
                                    {
                                        viewObj.IsLoading = true;
                                    }

                                    continue;
                                }

                                Log.Info("AOISceneView Load " + obj.Path);
                                //没有
                                self.DynamicSceneObjectMapObj[obj] = new AOISceneViewComponent.DynamicSceneViewObj();
                                viewObj           = self.DynamicSceneObjectMapObj[obj];
                                viewObj.IsLoading = true;
                                GameObjectPoolComponent.Instance.GetGameObjectAsync(obj.Path, (view) =>
                                {
                                    if (!viewObj.IsLoading) //加载出来后已经不需要的
                                    {
                                        GameObjectPoolComponent.Instance.RecycleGameObject(view);
                                        self.DynamicSceneObjectMapObj.Remove(obj);
                                    }
                                    viewObj.Obj               = view;
                                    viewObj.IsLoading         = false;
                                    view.transform.position   = obj.Position;
                                    view.transform.rotation   = obj.Rotation;
                                    view.transform.localScale = obj.Scale;
                                    view.transform.parent     = GlobalComponent.Instance.Scene;
                                }).Coroutine();
                            }
                        }
                        else //移除
                        {
                            if (self.DynamicSceneObjectMapCount.ContainsKey(obj))
                            {
                                self.DynamicSceneObjectMapCount[obj]--;
                            }
                            else
                            {
                                self.DynamicSceneObjectMapCount[obj] = -1;
                            }

                            //不需要显示但有
                            if (self.DynamicSceneObjectMapCount[obj] <= 0 && self.DynamicSceneObjectMapObj.ContainsKey(obj))
                            {
                                Log.Info("AOISceneView Remove " + obj.Path);
                                var viewObj = self.DynamicSceneObjectMapObj[obj];
                                if (viewObj.Obj == null) //还在加载
                                {
                                    viewObj.IsLoading = false;
                                }
                                else
                                {
                                    viewObj.Obj.SetActive(false);
                                    GameObjectPoolComponent.Instance.RecycleGameObject(viewObj.Obj);
                                    self.DynamicSceneObjectMapObj.Remove(obj);
                                }
                            }
                        }
                    }
                }

                temp.Dispose();
                self.LastGridX = x;
                self.LastGridY = y;
            }
            finally
            {
                coroutineLock?.Dispose();
            }
        }
Exemplo n.º 7
0
        public static async ETTask Init(this AOISceneViewComponent self)
        {
            #region 从XML初始化场景物体信息
            self.DynamicSceneMap = new Dictionary <string, AOISceneViewComponent.DynamicScene>();
            string xmlPath = "GameAssets/Config/Map.xml";
            var    content = await ResourcesComponent.Instance.LoadAsync <TextAsset>(xmlPath);

            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(content.text);
            // 使用 XPATH 获取所有 gameObject 节点
            XmlNodeList xmlNodeList = xmlDocument.LastChild.ChildNodes;
            foreach (XmlNode scene in xmlNodeList)
            {
                var sceneName = scene.Attributes["sceneName"].Value;
                AOISceneViewComponent.DynamicScene item = new AOISceneViewComponent.DynamicScene();
                self.DynamicSceneMap.Add(sceneName, item);
                item.Objects        = new List <AOISceneViewComponent.DynamicSceneObject>();
                item.GridMapObjects = new Dictionary <long, List <AOISceneViewComponent.DynamicSceneObject> >();
                foreach (XmlNode xmlNode in scene.ChildNodes)
                {
                    AOISceneViewComponent.DynamicSceneObject sceneObject = new AOISceneViewComponent.DynamicSceneObject();
                    string gameObjectName = xmlNode.Attributes["objectName"].Value;
                    string objectPath     = xmlNode.Attributes["objectPath"].Value;
                    sceneObject.Path = objectPath;
                    XmlNode positionXmlNode = xmlNode.SelectSingleNode("descendant::position");
                    XmlNode rotationXmlNode = xmlNode.SelectSingleNode("descendant::rotation");
                    XmlNode scaleXmlNode    = xmlNode.SelectSingleNode("descendant::scale");

                    if (positionXmlNode != null && rotationXmlNode != null && scaleXmlNode != null)
                    {
                        sceneObject.Position = new Vector3(float.Parse(positionXmlNode.Attributes["x"].Value),
                                                           float.Parse(positionXmlNode.Attributes["y"].Value), float.Parse(positionXmlNode.Attributes["z"].Value));
                        sceneObject.Rotation = Quaternion.Euler(new Vector3(float.Parse(rotationXmlNode.Attributes["x"].Value),
                                                                            float.Parse(rotationXmlNode.Attributes["y"].Value), float.Parse(rotationXmlNode.Attributes["z"].Value)));
                        sceneObject.Scale = new Vector3(float.Parse(scaleXmlNode.Attributes["x"].Value),
                                                        float.Parse(scaleXmlNode.Attributes["y"].Value), float.Parse(scaleXmlNode.Attributes["z"].Value));
                    }
                    item.Objects.Add(sceneObject);
                    int   x      = (int)Math.Floor(sceneObject.Position.x / self.GridLen);
                    int   y      = (int)Math.Floor(sceneObject.Position.z / self.GridLen);
                    float radius = Mathf.Sqrt(sceneObject.Scale.x * sceneObject.Scale.x + sceneObject.Scale.y * sceneObject.Scale.y + sceneObject.Scale.z * sceneObject.Scale.z) / 2;
                    int   count  = (int)Math.Ceiling(radius / self.GridLen);//环境多加一格
                    for (int i = x - count; i <= x + count; i++)
                    {
                        for (int j = y - count; j <= y + count; j++)
                        {
                            var res = AOIHelper.GetGridRelationshipWithOBB(sceneObject.Position, sceneObject.Rotation,
                                                                           sceneObject.Scale, self.GridLen, i, j);
                            if (res >= 0)
                            {
                                var id = AOIHelper.CreateCellId(i, j);
                                if (!item.GridMapObjects.ContainsKey(id))
                                {
                                    item.GridMapObjects.Add(id, new List <AOISceneViewComponent.DynamicSceneObject>());
                                }
                                item.GridMapObjects[id].Add(sceneObject);
                            }
                        }
                    }
                }
            }
            xmlDocument = null;
            #endregion
        }
Exemplo n.º 8
0
 /// <summary>
 /// 判断某个点是否在触发器移到指定位置后之内
 /// </summary>
 /// <param name="trigger"></param>
 /// <param name="position"></param>
 /// <param name="center"></param>
 /// <param name="rotation"></param>
 /// <returns></returns>
 public static bool IsPointInTrigger(this OBBComponent trigger, Vector3 position, Vector3 center, Quaternion rotation)
 {
     return(AOIHelper.IsPointInTrigger(position, center, rotation, trigger.Scale));
 }