Search Unity

Auto grass placement not working properly

Discussion in 'World Building' started by no00ob, Mar 10, 2019.

  1. no00ob

    no00ob

    Joined:
    Dec 13, 2017
    Posts:
    65
    Hello, I have this script which I found online that allows me to automatically add grass to specific textures on my terrain it works nicely except if I make the detailCountPerDetailPixel to bigger than 1 (I need to make it bigger to make my grass a little more dense) it only creates stripes of grass at certain points of the terrain which obviously isn't the correct behavior so if someone wants to try to take a look at this or redirect me to better and newer solution I'd me thankful.
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3.  
    4. public class GrassCreator : EditorWindow
    5. {
    6.  
    7.     public Terrain terrain;
    8.     public int detailIndexToMassPlace;
    9.     public int[] splatTextureIndicesToAffect = new int[] { 0, };
    10.     public int detailCountPerDetailPixel = 1;
    11.  
    12.     [MenuItem("Tools/Mass Grass Placement")]
    13.  
    14.     static void Init()
    15.     {
    16.         GrassCreator window = (GrassCreator)GetWindow(typeof(GrassCreator));
    17.         window.Show();
    18.         window.titleContent = new GUIContent("Grass Creator");
    19.         window.Focus();
    20.         window.ShowUtility();
    21.         if (Selection.activeGameObject && Selection.activeGameObject.GetComponent<Terrain>())
    22.         {
    23.             window.terrain = Selection.activeGameObject.GetComponent<Terrain>();
    24.         }
    25.     }
    26.  
    27.     void OnGUI()
    28.     {
    29.         GUILayout.Label("Grass Creator", EditorStyles.boldLabel);
    30.         GUILayout.Label("Settings for Grass", EditorStyles.centeredGreyMiniLabel);
    31.  
    32.         ScriptableObject ter = this;
    33.         SerializedObject terrainso = new SerializedObject(ter);
    34.         SerializedProperty property = terrainso.FindProperty("terrain");
    35.         EditorGUILayout.PropertyField(property, new GUIContent("Terrain Object:", "Place your terrain object in here."), true);
    36.         terrainso.ApplyModifiedProperties();
    37.  
    38.         if (terrain != null)
    39.         {
    40.             detailCountPerDetailPixel = EditorGUILayout.IntSlider(new GUIContent("Detail Counter Per Detail Pixel:", "The detail count per detail pixel"), detailCountPerDetailPixel, 1, 16);
    41.             detailIndexToMassPlace = EditorGUILayout.IntSlider(new GUIContent("Detail Index to Place:", "Select the grass index to mass place"), detailIndexToMassPlace, 0, terrain.terrainData.detailPrototypes.Length - 1);
    42.  
    43.             ScriptableObject target = this;
    44.             SerializedObject so = new SerializedObject(target);
    45.             SerializedProperty stringsProperty = so.FindProperty("splatTextureIndicesToAffect");
    46.             EditorGUILayout.PropertyField(stringsProperty, new GUIContent("Splat Textures to place on:", "Indicate the splatmap index to place on."), true);
    47.             so.ApplyModifiedProperties();
    48.  
    49.             if (GUILayout.Button(new GUIContent("Mass Place Grass", "Work the magic :D")))
    50.             {
    51.                 CreateGrass();
    52.             }
    53.         }
    54.     }
    55.  
    56.     void CreateGrass()
    57.     {
    58.  
    59.         if (!terrain)
    60.         {
    61.             Debug.LogError("You have not selected a terrain object");
    62.             return;
    63.         }
    64.  
    65.         if (detailIndexToMassPlace >= terrain.terrainData.detailPrototypes.Length)
    66.         {
    67.             Debug.LogError("You have chosen a detail index which is higher than the number of detail prototypes in your detail libary. Indices starts at 0");
    68.             return;
    69.         }
    70.  
    71.         if (splatTextureIndicesToAffect.Length > terrain.terrainData.splatPrototypes.Length)
    72.         {
    73.             Debug.LogError("You have selected more splat textures to paint on, than there are in your libary.");
    74.             return;
    75.         }
    76.  
    77.         for (int i = 0; i < splatTextureIndicesToAffect.Length; i++)
    78.         {
    79.             if (splatTextureIndicesToAffect[i] >= terrain.terrainData.splatPrototypes.Length)
    80.             {
    81.                 Debug.LogError("You have chosen a splat texture index which is higher than the number of splat prototypes in your splat libary. Indices starts at 0");
    82.                 return;
    83.             }
    84.         }
    85.  
    86.         if (detailCountPerDetailPixel > 16)
    87.         {
    88.             Debug.LogError("You have selected a non supported amount of details per detail pixel. Range is 0 to 16");
    89.             return;
    90.         }
    91.  
    92.         int alphamapWidth = terrain.terrainData.alphamapWidth;
    93.         int alphamapHeight = terrain.terrainData.alphamapHeight;
    94.         int detailWidth = terrain.terrainData.detailResolution;
    95.         int detailHeight = detailWidth;
    96.         float resolutionDiffFactor = (float)alphamapWidth / detailWidth;
    97.         float[,,] splatmap = terrain.terrainData.GetAlphamaps(0, 0, alphamapWidth, alphamapHeight);
    98.         int[,] newDetailLayer = new int[detailWidth, detailHeight];
    99.  
    100.         for (int i = 0; i < splatTextureIndicesToAffect.Length; i++)
    101.         {
    102.  
    103.             for (int j = 0; j < detailWidth; j++)
    104.             {
    105.  
    106.                 for (int k = 0; k < detailHeight; k++)
    107.                 {
    108.                     float alphaValue = splatmap[(int)(resolutionDiffFactor * j), (int)(resolutionDiffFactor * k), splatTextureIndicesToAffect[i]];
    109.                     newDetailLayer[j, k] = (int)Mathf.Round(alphaValue * ((float)detailCountPerDetailPixel)) + newDetailLayer[j, k];
    110.                 }
    111.  
    112.             }
    113.  
    114.         }
    115.         terrain.terrainData.SetDetailLayer(0, 0, detailIndexToMassPlace, newDetailLayer);
    116.     }
    117. }
    118.  
     
  2. no00ob

    no00ob

    Joined:
    Dec 13, 2017
    Posts:
    65
    Anyone? I got little more info, the bigger the detailCountPerDetailPixel gets the smaller the stripes become here are few examples on how the stripes look like. pic.jpeg
     

    Attached Files:

  3. dominguezriveradiego

    dominguezriveradiego

    Joined:
    Mar 7, 2019
    Posts:
    1
    I'm getting the same issue, i can't figure out what is causing it :S
     
  4. no00ob

    no00ob

    Joined:
    Dec 13, 2017
    Posts:
    65
    Sorry for not answering but I never got a notification. But if you still need help I found a way to fix it you need to decrease "Detail Resolution Per Patch" I set mine to 32 from 128 and also I recommend increasing the "Detail Resolution" I set mine from 1280 to 2048 and after that it worked flawlessly.