This class represents a tool that helps to prepare the scene to NavMesh baking. It will generate clone objects from colliders already in the scene. These clone objects will contain the renderer generated from the collider shape. Unity NavMesh baking works upon Renderers, so colliders are ignored. This tool fulfil the need of using only colliders for NavMesh baking. Read the instructions for more information.
Inheritance: EditorWindow
示例#1
0
        /// <summary>
        /// Creates and setup the feature on obj.
        /// </summary>
        /// <param name="obj">The object to spawn and configure the feature.</param>
        public void SetupFeature(GameObject obj)
        {
            // Add component
            obj.AddComponent <ArcTeleportManager>();

            // Secondary scripts
            GameObject navmesh = new GameObject();

            navmesh.name             = "Navmesh";
            navmesh.transform.parent = obj.transform;
            navmesh.AddComponent <BorderRenderer>();
            navmesh.AddComponent <NavMeshRenderer>();
            navmesh.transform.position = Vector3.zero;

            GameObject pointer = new GameObject();

            pointer.name             = "Pointer";
            pointer.transform.parent = obj.transform;
            pointer.AddComponent <ParabolicPointer>();
            pointer.transform.position = Vector3.zero;

            // Setup Component
            ArcTeleportManager teleportManager = obj.GetComponent <ArcTeleportManager>();

            ParabolicPointer pointerComponent = pointer.GetComponent <ParabolicPointer>();

            teleportManager.Pointer = pointerComponent;

            NavMeshRenderer navMeshHandler = navmesh.GetComponent <NavMeshRenderer>();
            BorderRenderer  border         = navmesh.GetComponent <BorderRenderer>();

            NavMeshHelper.ClearNavMesh(navMeshHandler, new SerializedObject(navMeshHandler), TeleportSettings);
            NavMeshHelper.UpdateNavMesh(navMeshHandler, new SerializedObject(navMeshHandler), TeleportSettings);
        }
示例#2
0
 public void LoadSceneAsync(string sceneName)
 {
     try
     {
         Log.Info("NavMeshSceneLoader.LoadSceneAsync", "start:" + sceneName);
         var operation = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
         if (operation == null)
         {
             Log.Error("LoadSceneAsync", "加载场景失败:" + sceneName);
             return;
         }
         operation.completed += op =>
         {
             Log.Info("NavMeshSceneLoader.LoadSceneAsync", "end:" + sceneName);
             NavMeshHelper.RefreshNavMeshInfo();//这个要更新,不然算出来的位置就有问题
             if (LocationManager.Instance != null)
             {
                 if (ActionBarManage.Instance != null && ActionBarManage.Instance.PersonnelToggle.isOn)
                 {
                     LocationManager.Instance.ShowLocation();//开始计算位置信息
                 }
             }
         };
         currentScene = sceneName;
     }
     catch (System.Exception ex)
     {
         Log.Error("NavMeshSceneLoader.LoadSceneAsync", ex.ToString());
     }
 }
示例#3
0
    //public static Vector3 GetDownPosition(Vector3 r)
    //{
    //    NavMeshHit hitInfo;
    //    Vector3 r1 = new Vector3(r.x, r.y - 100, r.z);
    //    CreatePoint(r1, "DownTarget", 0.1f, Color.red);
    //    if (NavMesh.Raycast(r, r1,out hitInfo, -1))
    //    {
    //        r = hitInfo.position;
    //    }
    //    else
    //    {
    //        //Debug.LogError("GetDownPosition No DownPosition ");
    //    }
    //    return r;
    //}

    public static Vector3 GetDownSample(Vector3 r, int count, float step)
    {
        Vector3 down        = r;
        float   distance    = float.MaxValue;
        float   floorHeight = 0;

        for (int i = 0; i < count; i++)
        {
            Vector3 r1 = new Vector3(r.x, r.y - i * step, r.z);
            var     p  = GetClosetPointByMeshEx(r1);

            if (IsDebug)
            {
                var t1 = NavMeshHelper.CreatePoint(r1, "DownTarget" + i, 0.1f, Color.red);
                var t2 = NavMeshHelper.CreatePoint(p, "DownTarget_Mesh" + i, 0.1f, Color.red);
                t2.transform.parent = t1.transform;
            }

            if (p.y < r.y)
            {
                if (floorHeight == 0)
                {
                    floorHeight = p.y;
                }
                var dis = Vector3.Distance(p, new Vector3(r1.x, floorHeight, r1.z));
                if (dis < distance)
                {
                    distance = dis;
                    down     = p;
                }
            }
        }
        return(down);
    }
示例#4
0
    /// <summary>
    /// 获取有效目标点
    /// </summary>
    /// <param name="targetPos"></param>
    /// <returns></returns>
    protected Vector3 GetDestination(Vector3 targetPos)
    {
        Vector3 destination = targetPos;

        InitNavMeshAgent();
        return(NavMeshHelper.GetClosetPoint(destination, agent));
    }
示例#5
0
    private IEnumerator ShowPosListAsync(List <Pos> posList)
    {
        DateTime   start  = DateTime.Now;
        List <Pos> result = null;

        InitPosPointsParent(); //删除并重新创建PosParent

        GameObject bluePrefab  = GetPrefab(Color.blue, 0.5f);
        GameObject redPrefab   = GetPrefab(Color.red, 0.5f);
        GameObject greenPrefab = GetPrefab(Color.green, 0.5f);
        GameObject blackPrefab = GetPrefab(Color.black, 0.5f);

        for (int i = 0; i < posList.Count && i < LimitCount; i++)
        {
            Pos pos = posList[i];
            //CreatePoint(pos);

            Vector3 v1 = new Vector3(pos.X, pos.Y, pos.Z);       //二维坐标
            Vector3 v2 = LocationManager.GetRealVector(v1);      //三维坐标

            Vector3 v3 = NavMeshHelper.GetClosetPoint(v2, null); //NavMesh上的坐标,这部分可能会比较花时间
            //Vector3 v4 = new Vector3(v3.x, v2.y, v3.z);//高度相同
            var dis = Vector3.Distance(v2, v3);

            GameObject prefab1 = null;
            GameObject prefab2 = blackPrefab;

            if (dis > RedDistance)//大于一个距离 5
            {
                prefab1 = redPrefab;
            }
            else if (dis < GreenDistanc)//大于一个距离 1
            {
                prefab1 = greenPrefab;
            }
            else
            {
                prefab1 = bluePrefab;
            }
            var p1 = CreatePoint(prefab1, v2, posPointParent.transform); //三维坐标
            p1.name = string.Format("{0}|{1}", i, v2);
            var p2 = CreatePoint(prefab2, v3, p1.transform);             //NavMesh上的坐标
            p2.name = "d:" + dis;
            //Gizmos.DrawLine(v2, v3);
            Debug.Log(string.Format("{0}/{1}", i, posList.Count));
            yield return(null);
        }

        GameObject.DestroyImmediate(bluePrefab);
        GameObject.DestroyImmediate(redPrefab);
        GameObject.DestroyImmediate(greenPrefab);
        GameObject.DestroyImmediate(blackPrefab);

        posPointParent.HighlightOn();

        Log.Info("ShowPosList:", (DateTime.Now - start).TotalMilliseconds + "ms");
    }
示例#6
0
 public void GetDownPoint()
 {
     //NavMeshHelper.downCount = downSampleCount;
     //NavMeshHelper.downStep = downStep;
     // showDownTest = true;
     var targetPos = followTarget.position;
     var down      = NavMeshHelper.GetDownSample(targetPos, downSampleCount, downStep);
     //NavMeshHelper.CreatePoint(down, "Down", 0.1f, Color.green);
 }
    public void ShowNavMeshPoints()
    {
        DateTime start = DateTime.Now;

        //NavMeshHit hitInfo;

        //foreach (GameObject point in navPoints)
        //{
        //    GameObject.DestroyImmediate(point);
        //}

        //if (NavMesh.FindClosestEdge(targetPos, out hitInfo, navMask))
        //{
        //    GameObject o = NavMeshHelper.CreatePoint(hitInfo.position, "Edge", 0.5f, Color.green);
        //    navPoints.Add(o);
        //}
        //else
        //{
        //    //Debug.LogError("FindClosestEdge No");
        //}

        //if (NavMesh.SamplePosition(targetPos, out hitInfo, sampleDistance, navMask))
        //{
        //    GameObject o = NavMeshHelper.CreatePoint(hitInfo.position, "Sample", 0.5f, Color.blue);
        //    navPoints.Add(o);
        //}
        //else
        //{
        //    //Debug.LogError("SamplePosition No");
        //}

        //if (NavMesh.Raycast(targetPos, agent.transform.position, out hitInfo, -1))
        //{
        //    GameObject o = NavMeshHelper.CreatePoint(hitInfo.position, "Raycast", 0.5f, Color.red);
        //    navPoints.Add(o);
        //}
        //else
        //{
        //    //Debug.LogError("No Raycast!!!!");
        //}


        NavMeshHelper.ScalePower = PointScale;

        //var pr = NavMeshHelper.GetClosetPoint(targetPos);
        ////navPoints.Add(NavMeshHelper.CreatePoint(pr, "ClosedPoint", 1f, Color.cyan));

        //TimeSpan time = DateTime.Now - start;
        //Debug.Log("ShowNavMeshPoints:" + time.TotalMilliseconds + "ms");

        NavMeshHelper.GetClosetPointAsync(targetPos, this.name, null, (pr, p) =>
        {
            TimeSpan time = DateTime.Now - start;
            Debug.Log("ShowNavMeshPoints:" + time.TotalMilliseconds + "ms");
        });
    }
示例#8
0
 public static void GetClosetPoint(Vector3 target, NavMeshAgent agent, Action <Vector3> callback)
 {
     NavMeshHelper.GetClosetPointAsync(target, "NPCTest", agent, (p, o) =>
     {
         if (callback != null)
         {
             callback(p);
         }
     });
 }
示例#9
0
    private void OnDisable()
    {
        tools_[(int)tool_type_].OnExit();

        helper_.ClearRefreshNavmesh();

        instance = null;
        helper_  = null;

        DataUninit();
    }
示例#10
0
    public void Start()
    {
        //Target = this.transform.position;

        if (agent != null)
        {
            var path = new NavMeshPath();
            agent.CalculatePath(transform.position, path);
            //Debug.Log(string.Format("{0},{1},{2}", this, path.status, path.corners.Length));
            PathDistance = NavMeshHelper.GetPathDistance(path);
            //Debug.Log(string.Format("{0},{1},{2},{3}", this.name, path.status, path.corners.Length, Distance));
            LineDistance = Vector3.Distance(transform.position, Target);
        }
    }
示例#11
0
    public NavPoint(string n, Vector3 p, Vector3 target, Color color, NavMeshAgent agent)
    {
        Name     = n;
        Position = p;
        Color    = color;

        if (NavMeshHelper.IsDebug)
        {
            var         t01  = NavMeshHelper.CreatePoint(p, n, 0.1f, color);
            NavTestInfo info = t01.AddComponent <NavTestInfo>();
            info.agent  = agent;
            info.Target = target;
        }

        Layer = NavMeshHelper.GetLayer(p);
    }
示例#12
0
    protected void SetSpeedByDistance()
    {
        if (targetPos == Vector3.zero)
        {
            return;                           //总不会那么巧,目标位置就是原点吧。
        }
        //bool r = agent.SetDestination(followTarget.position);
        if (!isPosInfoSet)
        {
            return;
        }
        distance = Vector3.Distance(targetPos, transform.position);
        //if(printDistance)
        //    Debug.Log("distance:" + distance);
        //Log.Info("NavAgentControllerBase.SetSpeedByDistance",string.Format("{0}->{1},distance:{2}", transform.position,targetPos,distance));
        SetSpeed(distance);

        if (enableJump)
        {
            if (distance > MaxDistance || isOnEnableWrap)//距离太远了,直接飞过去
            {
                //if (useWrap)
                //{
                //Vector3 destination = GetDestination(targetPos);
                ////Vector3 destination = NavMeshHelper.GetClosetPointEx(targetPos, agent);
                //if (destination == Vector3.zero)
                //{

                //}
                //else
                //{
                //    var r=agent.Warp(destination);//要用这个
                //    Log.Info("NavAgentControllerBase.SetSpeedByDistance", string.Format("Jump(Warp) distance:{0}|name:{1}|destination:{2}|wrap:{3}|isOnEnableWrap:{4}",
                //        distance , this.name , destination , r, isOnEnableWrap));
                //}

                NavMeshHelper.GetClosetPointAsync(targetPos, this.name, agent, (destination, o) =>
                {
                    var r = agent.Warp(destination);//要用这个
                    Log.Info("NavAgentControllerBase.SetSpeedByDistance", string.Format("Jump(Warp) distance:{0}|name:{1}|destination:{2}|wrap:{3}|isOnEnableWrap:{4}|MaxDistance:{5}",
                                                                                        distance, this.name, destination, r, isOnEnableWrap, MaxDistance));
                });

                isOnEnableWrap = false;
            }
        }
    }
示例#13
0
    private void OnEnable()
    {
        instance = this;
        helper_  = (NavMeshHelper)target;

        root_paht_ = Application.dataPath + "/";

        tools_[(int)ToolType.None]          = new ToolBase();
        tools_[(int)ToolType.TestNavMesh]   = new TestNavMeshTool();
        tools_[(int)ToolType.SelectArea]    = new SelectAreaTool();
        tools_[(int)ToolType.AddArea]       = new AddAreaTool();
        tools_[(int)ToolType.EditAreaColor] = new EditAreaColorTool();
        tools_[(int)ToolType.TestArea]      = new TestAreaTool();

        DataInit();

        tools_[(int)tool_type_].OnEnter();
    }
示例#14
0
    public override void OnGUI()
    {
        GUILayout.BeginVertical();

        if (GUILayout.Button("刷新修改", GUILayout.Width(130), GUILayout.Height(20)))
        {
            NavMeshHelperEditor.instance.RefreshArea();
        }

        NavMeshHelper helper = NavMeshHelperEditor.instance.helper_;

        for (int i = 0; i < ConvexUtilities.area_max; ++i)
        {
            helper.area_color[i] = EditorGUILayout.ColorField("area id:" + i.ToString(), helper.area_color[i]);
        }

        GUILayout.EndVertical();
    }
示例#15
0
    public void SetNavAgent(LocationObject o, Action callback)
    {
        Log.Info("PathFindingManager.SetNavAgent", "o:" + o.transform.name);
        if (SystemSettingHelper.locationSetting.EnableNavMesh == false)
        {
            return;                                                            //不启用NavMesh
        }
        if (o == null)
        {
            return;
        }
        if (useNavAgent)
        {
            var agent = o.gameObject.AddComponent <NavAgentController>();//往原来物体上加NavAgentController来控制物体移动
            o.navAgent = agent;
        }
        else if (useFollowNavAgent)
        {
            //if (FollowAgent)
            {
                if (o.navAgentFollow == null)
                {
                    Log.Debug("PathFindingManager.SetNavAgent", string.Format("{0},{1},{2}", o.name, o.transform.position, o.gameObject.activeInHierarchy));

                    //var pos = o.transform.position;
                    //InstantiateNavAgent(o, pos);

                    NavMeshHelper.GetClosetPointAsync(o.transform.position, o.name, null, (pos, obj) =>
                    {
                        InstantiateNavAgent(o, pos);
                        if (callback != null)
                        {
                            callback();
                        }
                    });
                }
            }
        }
        else
        {
            //不使用NavMesh
        }
    }
示例#16
0
    public void ShowPath()
    {
        //Path = agent.CalculatePath(Target);

        Path = new NavMeshPath();
        agent.CalculatePath(Target, Path);
        Debug.Log(string.Format("{0},{1}", Path.status, Path.corners.Length));

        foreach (var item in testPoints)
        {
            GameObject.Destroy(item);
        }
        //foreach (var item in Path.corners)
        //{
        //    GameObject tp = NavMeshHelper.CreatePoint(item, "" + item, 0.1f, Color.black);
        //    testPoints.Add(tp);
        //}

        PathDistance = NavMeshHelper.GetPathDistance(Path);
    }
示例#17
0
 public void ShowNevMesh()
 {
     NavMeshHelper.ShowNavMesh(navMeshObj);
 }
 public void GetClosetPoint()
 {
     NavMeshHelper.GetClosetPointAsync(this.transform.position, "Test", agent, null);
 }
示例#19
0
    protected void SetDestination(Vector3 pos, Action <bool> callback)
    {
        Log.Info("NavAgentControllerBase.SetDestination", string.Format("{0}->{1},obj:{2}", transform.position, pos, this));
        if (lastPos == pos)//坐标不变,不用计算处理。
        {
            if (callback != null)
            {
                callback(false);
            }
            return;
        }
        //if (lastPos == Vector3.zero)//说明是第一次,直接跳过去吧
        //{
        //    lastPos = pos;
        //    Vector3 posNew=NavMeshHelper.GetClosetPointEx(pos, agent);
        //    if (agent != null)
        //    {
        //        if (agent.gameObject.activeInHierarchy)
        //        {
        //
        //        }
        //        else
        //        {
        //            transform.position = posNew;
        //        }
        //    }
        //    else
        //    {
        //        transform.position = posNew;
        //    }
        //            if (callback != null)
        //    {
        //        callback(true);
        //    }
        //    return;
        //}
        lastPos = pos;

        //Log.Info("NavAgentControllerBase.SetDestination", string.Format("pos:{0},obj:{1}",pos,this));
        if (IsBusyUpdatePosition)
        {
            //Log.Info("NavAgentControllerBase.UpdatePosition", "IsBusyUpdatePosition");
            if (callback != null)
            {
                callback(false);
            }
            return;
        }
        DateTime start = DateTime.Now;

        IsBusyUpdatePosition = true;
        NavMeshHelper.GetClosetPointAsync(pos, this.name, agent, (destination, p) => //多线程异步方式计算,避免影响性能
        {
            try
            {
                //Log.Info("NavAgentControllerBase.SetDestination", string.Format("{0}=>{1},{2}", pos,destination, this));
                if (SystemSettingHelper.IsDebug())//调试模式下,查看接下来的移动方向
                {
                    if (ArcManager.Instance != null)
                    {
                        if (p != null)
                        {
                            ArcManager.Instance.SetLine(gameObject.transform, p.transform);
                        }
                    }
                }

                if (agent != null)
                {
                    if (agent.gameObject.activeInHierarchy)
                    {
                        if (EnableUpdate == false)//代表第一次
                        {
                            Log.Info("NavAgentControllerBase.SetDestination", string.Format("First Wrap!! pos:{0},obj:{1}", pos, this));
                            agent.Warp(destination);
                        }
                        else
                        {
                            bool r = agent.SetDestination(destination); //Agent被关闭或者被销毁,调用这个方法会报错
                            if (r == false)                             //人物物体不在NavMesh上,立刻跳到目标位置
                            {
                                Log.Info("NavAgentControllerBase.SetDestination", string.Format("Wrap pos:{0},obj:{1}", pos, this));
                                //this.transform.position = destination;
                                agent.Warp(destination);//要用这个,用上面那句话,"不在NavMesh上"的问题会一直出现,要用Warp才会重新计算
                            }
                            else
                            {
                                HisPosInfo hisPosInfo = posInfo as HisPosInfo; //假如是历史数据
                                if (hisPosInfo != null)
                                {
                                    var current = hisPosInfo.CurrentPosInfo;
                                    var next    = current.Next;

                                    if (next != null)
                                    {
                                        TimeSpan t = next.Time - current.Time; //下一个点的时间
                                                                               //float distance = Vector3.Distance(next.Vec, current.Vec); //下一个点的距离

                                        //Log.Info("NavAgentControllerBase.UpdatePosition", string.Format("{0}=>{1},time:{2},distance:{3}", current.Vec, next.Vec, time, distance));
                                        this.timespan = t.TotalSeconds;//时间越长,走的越慢
                                    }
                                }
                            }
                        }

                        EnableUpdate = true;
                    }
                    else
                    {
                        Log.Error("NavAgentControllerBase.SetDestination", "agent.gameObject.activeInHierarchy==false:" + this);
                    }
                }
                else
                {
                    Log.Error("NavAgentControllerBase.SetDestination", "agent==null:" + this);
                }
            }
            catch (Exception ex)
            {
                Log.Error("NavAgentControllerBase.SetDestination", "Exception:" + ex);
            }
            finally
            {
                IsBusyUpdatePosition = false;
                TimeSpan time        = DateTime.Now - start;

                if (callback != null)
                {
                    callback(false);
                }
            }



            //Log.Info("NavAgentControllerBase.UpdatePosition", NavMeshHelper.Log);
            //Log.Info("NavAgentControllerBase.SetDestination", "UpdatePosition End time:" +time.TotalMilliseconds+"ms");
        });

        //IsBusyUpdatePosition = true;
        //var destination = NavMeshHelper.GetClosetPoint(pos); //  => //多线程异步方式计算,避免影响性能
        //if (agent != null && agent.gameObject.activeInHierarchy)
        //{
        //    bool r = agent.SetDestination(destination); //Agent被关闭或者被销毁,调用这个方法会报错
        //    Log.Info("NavAgentControllerBase.UpdatePosition", "r:" + r);
        //    if (r == false) //人物物体不在NavMesh上,立刻跳到目标位置
        //    {
        //        //this.transform.position = destination;
        //        agent.Warp(destination);//要用这个,用上面那句话,"不在NavMesh上"的问题会一直出现,要用Warp才会重新计算
        //    }
        //}

        //IsBusyUpdatePosition = false;
        //TimeSpan time = DateTime.Now - start;
        ////Log.Info("NavAgentControllerBase.UpdatePosition", NavMeshHelper.Log);
        //Log.Info("NavAgentControllerBase.UpdatePosition", "UpdatePosition End time:" + time.TotalMilliseconds + "ms");

        //return true;
    }
示例#20
0
        /// <summary>
        /// Execute when Update Navmesh button is clicked.
        /// </summary>
        private void OnNavmeshUpdateClick()
        {
            GameObject featureObject = FindFeatureOfType(typeof(ArcTeleportManager));

            if (featureObject == null)
            {
                Debug.LogError("Add Arc Teleport before clicking Update Navmesh.");
            }
            else
            {
                ArcTeleportManager arcTeleportManager = featureObject.GetComponent <ArcTeleportManager>();


                NavMeshRenderer mesh = featureObject.transform.Find("Navmesh").GetComponent <NavMeshRenderer>();

                // Area Mask //
                string[] areas      = GameObjectUtility.GetNavMeshAreaNames();
                int[]    area_index = new int[areas.Length];
                int      temp_mask  = 0;
                for (int x = 0; x < areas.Length; x++)
                {
                    area_index[x] = GameObjectUtility.GetNavMeshAreaFromName(areas[x]);
                    temp_mask    |= ((TeleportSettings.NavAreaMask >> area_index[x]) & 1) << x;
                }
                EditorGUI.BeginChangeCheck();
                temp_mask = EditorGUILayout.MaskField("Area Mask", temp_mask, areas);
                if (EditorGUI.EndChangeCheck())
                {
                    TeleportSettings.NavAreaMask = 0;
                    for (int x = 0; x < areas.Length; x++)
                    {
                        TeleportSettings.NavAreaMask |= (((temp_mask >> x) & 1) == 1 ? 0 : 1) << area_index[x];
                    }
                    TeleportSettings.NavAreaMask = ~TeleportSettings.NavAreaMask;
                }

                // Sanity check for Null properties //
                bool HasMesh = (mesh.SelectableMesh != null && mesh.SelectableMesh.vertexCount != 0) || (mesh.SelectableMeshBorder != null && mesh.SelectableMeshBorder.Length != 0);

                bool MeshNull   = mesh.SelectableMesh == null;
                bool BorderNull = mesh.SelectableMeshBorder == null;

                if (MeshNull || BorderNull)
                {
                    string str = "Internal Error: ";
                    if (MeshNull)
                    {
                        str += "Selectable Mesh == null.  ";
                    }
                    if (BorderNull)
                    {
                        str += "Border point array == null.  ";
                    }
                    str += "This may lead to strange behavior or serialization.  Try updating the mesh or delete and recreate the Navmesh object.  ";
                    str += "If you are able to consistently get a Vive Nav Mesh object into this state, please submit a bug report.";
                    EditorGUILayout.HelpBox(str, MessageType.Error);
                }

                UnityEngine.AI.NavMeshTriangulation tri = UnityEngine.AI.NavMesh.CalculateTriangulation();
                int vert_size, tri_size;

                NavMeshHelper.CullNavmeshTriangulation(ref tri, TeleportSettings.NavAreaMask, out vert_size, out tri_size);

                Mesh m = NavMeshHelper.ConvertNavmeshToMesh(tri, vert_size, tri_size);
                // Can't use SerializedProperties here because BorderPointSet doesn't derive from UnityEngine.Object
                mesh.SelectableMeshBorder = NavMeshHelper.FindBorderEdges(m);

                TeleportSettings.SelectableMesh = m;
                mesh.SelectableMesh             = mesh.SelectableMesh;
                TeleportSettings.Save();
            }
        }