public static GameObject CombineMeshes(
        bool processObjectsByTag   = false,
        string rmbTag              = null,
        bool processObjectsByLayer = false,
        int rmbLayer = 0,
        bool destroyOriginalObjects       = false,
        bool keepOriginalObjectReferences = false,
        bool combineByGrid           = false,
        MeshBatcherGridType gridType = MeshBatcherGridType.Grid2D,
        float gridSize = 0)
    {
        // Build Objects List
        var objectsToBatch = new List <GameObject>();

        // Add objects by tag
        if (processObjectsByTag && rmbTag != null)
        {
            objectsToBatch.AddRange(GameObject.FindGameObjectsWithTag(rmbTag));
        }

        // Add objects by layer
        if (processObjectsByLayer)
        {
            GameObject[] allGameObjects = Object.FindObjectsOfType <GameObject>();
            for (int i = 0; i < allGameObjects.Length; i++)
            {
                GameObject go = allGameObjects[i];
                if (go.layer == rmbLayer)
                {
                    objectsToBatch.Add(go);
                }
            }
        }

        return(CombineMeshes(objectsToBatch.ToArray(), destroyOriginalObjects, keepOriginalObjectReferences, combineByGrid, gridType, gridSize));
    }
    public static GameObject CombineMeshes(
        GameObject[] objectsToBatch, bool destroyOriginalObjects = false, bool keepOriginalObjectReferences = false, bool combineByGrid = false,
        MeshBatcherGridType gridType = MeshBatcherGridType.Grid2D,
        float gridSize = 0)
    {
        if (objectsToBatch == null || objectsToBatch.Length == 0)
        {
            Debug.LogWarning("Runtime Mesh Batcher warning: no objects found to be combined.");
            return(null);
        }
        GameObject combinedMeshParent;

        if (combineByGrid && gridSize <= 0)
        {
            Debug.LogWarning("Runtime Mesh Batcher warning: Grid Size must be superior to 0. Continuing batching without grid.");
            combineByGrid = false;
        }


        if (combineByGrid)
        {
            var objectsByCell = new Dictionary <string, List <GameObject> >();
            switch (gridType)
            {
            case MeshBatcherGridType.Grid2D:
                foreach (var gameObject in objectsToBatch)
                {
                    var    position = gameObject.transform.position;
                    var    xIndex   = GetGridIndex(position.x, gridSize);
                    var    zIndex   = GetGridIndex(position.z, gridSize);
                    string key      = xIndex + "_" + zIndex;
                    if (!objectsByCell.ContainsKey(key))
                    {
                        objectsByCell[key] = new List <GameObject>();
                    }
                    objectsByCell[key].Add(gameObject);
                }
                break;

            case MeshBatcherGridType.Grid3D:
                foreach (var gameObject in objectsToBatch)
                {
                    var    position = gameObject.transform.position;
                    var    xIndex   = GetGridIndex(position.x, gridSize);
                    var    yIndex   = GetGridIndex(position.y, gridSize);
                    var    zIndex   = GetGridIndex(position.z, gridSize);
                    string key      = xIndex + "_" + yIndex + "_" + zIndex;
                    if (!objectsByCell.ContainsKey(key))
                    {
                        objectsByCell[key] = new List <GameObject>();
                    }
                    objectsByCell[key].Add(gameObject);
                }
                break;
            }
            combinedMeshParent = CreateParent();
            foreach (var gameObjects in objectsByCell.Values)
            {
                var combinedMesh = CreateStaticMesh(gameObjects.ToArray(), destroyOriginalObjects, true);
                SetParent(combinedMesh, combinedMeshParent);
            }
        }
        else
        {
            combinedMeshParent = CreateStaticMesh(objectsToBatch, destroyOriginalObjects);
        }
        if (keepOriginalObjectReferences)
        {
            if (originalObjetReferences == null)
            {
                originalObjetReferences = new Dictionary <GameObject, GameObject[]>();
            }
            originalObjetReferences[combinedMeshParent] = objectsToBatch;
        }

        return(combinedMeshParent);
    }