Separate mesh by loose parts

Please help I’m stuck on this part of my project for 2 months !

Hi,

I have a huge map in my game which include a whole city it’s nearly 50km x 50km but the whole model is separated in 20 meshes and so many buildings are merged in one mesh.

The problem is:

I need the user be able to select buildings one by one.


I wrote the following script to find nearest vertex to your click and then check all vertices and triangles to detect connected ones to the clicked vertex, and then create new mesh and game object using this data but its not working.

MeshSeparator.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MeshSeparator : MonoBehaviour
{
    public GameObject SelectedBuilding;
    public Mesh SelectedMesh,SeparatedMesh;
    int SelectedVertexIndex;
    public List<int> ConnectedTriangles = new List<int>();
    public int[] OriginaleTriangles;
    public List<Vector3> ConnectedVerticesPos = new List<Vector3>();
    public List<int> ConnectedVertices = new List<int>();
    public List<int> Vertices = new List<int>();
    //--------------------Variables------------------------------------------------------------------
    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            ShootRay();
        }
    }

    public void ShootRay() 
    {
       
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;
        if (Physics.Raycast(ray ,out hit))
        {
            if (hit.transform.CompareTag("Building"))
            {
                SelectedBuilding = hit.transform.gameObject;
                SelectedMesh = SelectedBuilding.GetComponent<MeshFilter>().mesh;
              print("Vert and triangle count " + SelectedMesh.vertexCount +"  " + SelectedMesh.triangles.Length + "    " + SelectedMesh.GetIndices(0).Length);
                //StartCoroutine(Test());
                StartCoroutine(FindNearestVertex(hit.point));
            }
        }
    }
    public IEnumerator FindNearestVertex(Vector3 Point) 
    {
        float distance = 10;
        SelectedVertexIndex = 0;
        for (int i = 0; i < SelectedMesh.vertexCount; i++)
        {
            if (Vector3.Distance(SelectedMesh.vertices[i],Point) < distance)
            {
                SelectedVertexIndex = i;
                distance = Vector3.Distance(SelectedMesh.vertices[i], Point);
            }
            if (SelectedMesh.vertexCount > 100)
            {
                yield return new WaitForEndOfFrame();
            }
        }
        StartCoroutine(FindConnectedVertices());
    }
    public IEnumerator FindConnectedVertices() 
    {
        int TriangleCount = 1;
        int ConnectedTriangleCount = 1;
        ConnectedTriangles.Add(SelectedVertexIndex);
        for (int i = 0; i < SelectedMesh.triangles.Length; i+=3)
        {
            print("Triangle " + TriangleCount + ": " + SelectedMesh.triangles[i]+" , " + SelectedMesh.triangles[i+1] + " , " + SelectedMesh.triangles[i+2]);
            if (ConnectedTriangles.Contains(SelectedMesh.triangles[i]) || ConnectedTriangles.Contains(SelectedMesh.triangles[i+1]) || ConnectedTriangles.Contains(SelectedMesh.triangles[i+2]))
            {
                ConnectedTriangles.Add(SelectedMesh.triangles[i]);
                ConnectedTriangles.Add(SelectedMesh.triangles[i+1]);
                ConnectedTriangles.Add(SelectedMesh.triangles[i+2]);
                ConnectedTriangleCount++;
            }
            TriangleCount++;
            yield return new WaitForEndOfFrame();
        }
        ConnectedTriangles.RemoveAt(0);
        for (int i = 0; i < SelectedMesh.vertices.Length; i++)
        {
            for (int j = 0; j < ConnectedTriangles.Count; j++)
            {
                if (!ConnectedTriangles.Contains(i))
                {
                    if (SelectedMesh.vertices[ConnectedTriangles[j]] == SelectedMesh.vertices[i])
                    {
                        print("this triangle vertex : " + ConnectedTriangles[j] + "was neighbour to : " + i);
                        ConnectedVertices.Add(i);
                    }
                }
                yield return new WaitForEndOfFrame();
            }
        }
        for (int i = 0; i < SelectedMesh.triangles.Length; i += 3)
        {
            print("Triangle " + TriangleCount + ": " + SelectedMesh.triangles[i] + " , " + SelectedMesh.triangles[i + 1] + " , " + SelectedMesh.triangles[i + 2]);
            if (ConnectedVertices.Contains(SelectedMesh.triangles[i]) || ConnectedVertices.Contains(SelectedMesh.triangles[i + 1]) || ConnectedVertices.Contains(SelectedMesh.triangles[i + 2]))
            {
                ConnectedTriangles.Add(SelectedMesh.triangles[i]);
                ConnectedTriangles.Add(SelectedMesh.triangles[i + 1]);
                ConnectedTriangles.Add(SelectedMesh.triangles[i + 2]);
                ConnectedTriangleCount++;
            }
            TriangleCount++;
            yield return new WaitForEndOfFrame();
        }
        print("Connected Triangle Count : " + ConnectedTriangleCount);
        CreateMesh();
    }

    public void CreateMesh() 
    {
        SeparatedMesh = new Mesh();
        Vertices = new List<int>();
        for (int i = 0; i <ConnectedTriangles.Count ; i++)
        {
            if (!Vertices.Contains(ConnectedTriangles[i]))
            {
                Vertices.Add(ConnectedTriangles[i]);
            }
        }
        Vertices.Sort();
        Vector3[] SeparatedVertecies = new Vector3[Vertices.Count];
        for (int i = 0; i < Vertices.Count; i++)
        {
            SeparatedVertecies[i] = SelectedMesh.vertices[Vertices[i]];
        }
        SeparatedMesh.vertices = SeparatedVertecies;
        SeparatedMesh.triangles = ConnectedTriangles.ToArray();
        SeparatedMesh.RecalculateBounds();
        SeparatedMesh.RecalculateNormals();
        GameObject obj = new GameObject();
        obj = Instantiate(obj);
        MeshFilter filter = obj.AddComponent<MeshFilter>();
        MeshRenderer renderer = obj.AddComponent<MeshRenderer>();
        filter.mesh = SeparatedMesh;
        OriginaleTriangles = SelectedMesh.triangles;
    }

    public IEnumerator Test() 
    {
        for (int i = 0; i < SelectedMesh.GetIndices(0).Length; i++)
        {
            yield return new WaitForEndOfFrame();
        }
    }
}

Image of one chunk of my map