Returned dictionary key is the grass index inside TerrainData.detailPrototypes array and value holds the combined meshes associated to that index.
grassCombineType - Grass meshes combine type:
GrassCombineType.ByTexture - Grass meshes are combined based on the used grass texture.
GrassCombineType.ByTextureWithAtlas - Grass meshes are combined based on the used grass texture and mesh UV is generated based on the provided GrassAtlasTexture.
GrassCombineType.Everything - Combines all grass meshes into one file and for each mesh UV is generated based on the provided GrassAtlasTexture.
GrassMeshTexcoord2.PivotPoint - Bakes current grass quad mesh's pivot point's local position.
GrassMeshTexcoord2.BaseUV - Bakes current grass quad mesh's initial UV coordinates that will be overwritten in the case of using GrassAtlasTexture.
calculateHealthAndDryColor - Bakes prototype's health and dry colors.
Dictionary<Texture2D, Rect> atlasRect - In the case of using GrassAtlasTexture, this property should provide collection of GrassTextures and UV coordinates associated with this texture inside GrassAtlasTexture.
exportPercentage - Percentage of the combined grass objects in the range of [0.01, 100]
maxVertexCountPerCombinedMesh - Defines how much vertices combined mesh(es) will contain.
Theoretically Unity can create mesh with 4 billion vertices, but for run-time use it is better to use more logical values. Based on the used vertex count, generated meshes will be in 16 or 32 bits index format.
int grassMeshSidesCount, float grassMeshDistortion - Specifies how much sides each grass quad mesh will contain and how much offset distortion they will have.
//Example of exporting grass from TerrainData
//and generating combined meshes by used texture
//Exporting terrain mesh
Mesh terrainMesh = terrainData.TerrainToMesh().ExportMesh(100, 100);
//Creaing GameObject using terrain mesh
GameObject terrainGO = new GameObject("Terrain");
terrainGO.AddComponent<MeshFilter>().sharedMesh = terrainMesh;
terrainGO.AddComponent<MeshRenderer>().sharedMaterial = new Material(TerrainToMeshUtilities.GetDefaultShader());
//Exporting grass from TerrainData
TerrainToMeshPrototype[] grassPrototypes = terrainData.TerrainToMesh().ExportPrototypes(TerrainToMeshEnum.Prototype.Grass);
//Combining 100% of grassPrototypes into meshes with each one with 65K vertices
Dictionary<int, Mesh[]> grassMeshes = TerrainToMeshUtilities.ConvertPrototypesToGrassMeshes(grassPrototypes,
TerrainToMeshEnum.GrassCombineType.ByTexture,
TerrainToMeshEnum.GrassMeshTexcoord2.None,
true,
null,
100,
65000);
//Creating materials for each layer
Dictionary<int, Material> grassMaterials = new Dictionary<int, Material>();
foreach (var item in grassMeshes)
{
Texture2D grassTexture = terrainData.detailPrototypes[item.Key].prototypeTexture;
Material material = new Material(TerrainToMeshUtilities.GetDefaultShader());
//Setting up material to use grass texture for '_MainTex' and enabling Alpha Cutout
TerrainToMeshUtilities.SetupDefaultMaterial(material, grassTexture, true, null, null, null);
material.name = grassTexture.name;
grassMaterials.Add(item.Key, material);
}
//Instantiating gameObject with grass meshes
foreach (var item in grassMeshes)
{
Mesh[] meshes = item.Value;
for (int i = 0; i < meshes.Length; i++)
{
GameObject grassGO = new GameObject($"Grass (Layer : {item.Key}) {grassMaterials[item.Key].name}");
grassGO.AddComponent<MeshFilter>().sharedMesh = meshes[i];
grassGO.AddComponent<MeshRenderer>().sharedMaterial = grassMaterials[item.Key];
grassGO.transform.SetParent(terrainGO.transform);
}
}
//Example of exporting grass from TerrainData,
//and generating combined meshes by used texture
//Exporting terrain mesh
Mesh terrainMesh = terrainData.TerrainToMesh().ExportMesh(100, 100);
//Creaing GameObject using terrain mesh
GameObject terrainGO = new GameObject("Terrain");
terrainGO.AddComponent<MeshFilter>().sharedMesh = terrainMesh;
terrainGO.AddComponent<MeshRenderer>().sharedMaterial = new Material(TerrainToMeshUtilities.GetDefaultShader());
//Exporting grass from TerrainData
TerrainToMeshPrototype[] grassPrototypes = terrainData.TerrainToMesh().ExportPrototypes(TerrainToMeshEnum.Prototype.Grass);
//Exporting grass atlas texture from TerrainData
Dictionary<Texture2D, Rect> atlasUVRect;
Texture2D grassAtlasTexture = terrainData.TerrainToMesh().ExportGrassAtlasTexture(1024, out atlasUVRect);
//Combining 100% of grassPrototypes into meshes with each one with 65K vertices
Dictionary<int, Mesh[]> grassMeshes = TerrainToMeshUtilities.ConvertPrototypesToGrassMeshes(grassPrototypes,
TerrainToMeshEnum.GrassCombineType.ByTextureWithAtlas,
TerrainToMeshEnum.GrassMeshTexcoord2.None,
true,
atlasUVRect,
100,
65000);
//Creating material using GrassAtlasTexture
Material grassAtlasMaterial = new Material(TerrainToMeshUtilities.GetDefaultShader());
grassAtlasMaterial.name = terrainData.name + " Grass Atlas";
//Setting up material to use GrassAtlasTexture for '_MainTex' and enabling Alpha Cutout
TerrainToMeshUtilities.SetupDefaultMaterial(grassAtlasMaterial, grassAtlasTexture, true, null, null, null);
//Instantiating gameObject with grass meshes
foreach (var item in grassMeshes)
{
Mesh[] meshes = item.Value;
for (int i = 0; i < meshes.Length; i++)
{
GameObject grassGO = new GameObject($"Grass (Layer: {item.Key})");
grassGO.AddComponent<MeshFilter>().sharedMesh = meshes[i];
grassGO.AddComponent<MeshRenderer>().sharedMaterial = grassAtlasMaterial;
grassGO.transform.SetParent(terrainGO.transform);
}
}
//Example of exporting grass from TerrainData
//and combining them all into one mesh
//Exporting terrain mesh
Mesh terrainMesh = terrainData.TerrainToMesh().ExportMesh(100, 100);
//Creaing GameObject using terrain mesh
GameObject terrainGO = new GameObject("Terrain");
terrainGO.AddComponent<MeshFilter>().sharedMesh = terrainMesh;
terrainGO.AddComponent<MeshRenderer>().sharedMaterial = new Material(TerrainToMeshUtilities.GetDefaultShader());
//Exporting grass from TerrainData
TerrainToMeshPrototype[] grassPrototypes = terrainData.TerrainToMesh().ExportPrototypes(TerrainToMeshEnum.Prototype.Grass);
//Exporting grass atlas texture from TerrainData
Dictionary<Texture2D, Rect> atlasUVRect;
Texture2D grassAtlasTexture = terrainData.TerrainToMesh().ExportGrassAtlasTexture(1024, out atlasUVRect);
//Combining 100% of grassPrototypes into meshes with each one with 65K vertices
Dictionary<int, Mesh[]> grassMeshes = TerrainToMeshUtilities.ConvertPrototypesToGrassMeshes(grassPrototypes,
TerrainToMeshEnum.GrassCombineType.Everything,
TerrainToMeshEnum.GrassMeshTexcoord2.None,
true,
atlasUVRect,
100,
65000);
//Creating material using GrassAtlasTexture
Material grassAtlasMaterial = new Material(TerrainToMeshUtilities.GetDefaultShader());
grassAtlasMaterial.name = terrainData.name + " Grass Atlas";
//Setting up material to use GrassAtlasTexture for '_MainTex' and enabling Alpha Cutout
TerrainToMeshUtilities.SetupDefaultMaterial(grassAtlasMaterial, grassAtlasTexture, true, null, null, null);
//Instantiating gameObject with grass meshes
foreach (var item in grassMeshes)
{
Mesh[] meshes = item.Value;
for (int i = 0; i < meshes.Length; i++)
{
GameObject grassGO = new GameObject("Grass");
grassGO.AddComponent<MeshFilter>().sharedMesh = meshes[i];
grassGO.AddComponent<MeshRenderer>().sharedMaterial = grassAtlasMaterial;
grassGO.transform.SetParent(terrainGO.transform);
}
}