I know that I can mass place trees, I was wondering if I could mass place grass as well?
It isn’t built in, but you could write a script that does this.
You won’t find any documentation on it, but check this thread: http://forum.unity3d.com/viewtopic.php?p=261085
It has all the members you need to use in it
Will do, thanks for the reply.
I made a mass place grass editor script some weeks ago, in which you simply define which index number your grass detail object has, and then define which of your splat textures you want to to fill with grass details (their indexes in the terrain component). Lastly you define how dense you want it (1-16). And click ok.
Takes 1 second to paint even grass at the complete terrain this way ![]()
I can upload it tomorrow, when I’m at work…
You the man.
Hi again
Here’s the mass grass placement script. This should be saved in a folder called “Editor” alongside you standard-/pro asset folders.
This was made for my own use, and isn’t very descriptive in its form. I took the time to put in some returns if some settings are invalid, but other than that, you are on your own.
Some things to consider:
Setting the detail density to one, doesn’t mean only one is placed per detail control pixel. It’s just the lowest amount. The same goes for 16. (EDIT: WRONG!)
For non coders using this, be aware that indices starts at 0. The first detail object in your terrain detail libary will have the number “0”, and if you have 8 different detail objects, and want to place the last on the list, you would write index number “7”. The splat texture property is an array, and you first define how many different textures in your terrain splat libary you want to affect. And afterwards you write the actual indices.
You should also be aware that you will delete all previously placements of the given detail object. So if you have already placed grass at some places, that will be reset. Kinda like the mass tree placement functionality works…
Lastly this is without undo functionality. If you want to remove all grass previously placed, then just define the detail and a splat texture, and write “0” as the amount you want to place…
When you have imported this into your project, it will be found under the Terrain menu, called “Mass Grass Placement”
Good luck, hope it helps some. And if you have problems, just write in here…
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.IO;
public class GrassCreator : ScriptableWizard {
public Terrain terrain;
public int detailIndexToMassPlace;
public int[] splatTextureIndicesToAffect;
public int detailCountPerDetailPixel = 0;
[MenuItem ("Terrain/Mass Grass Placement")]
static void createWizard() {
ScriptableWizard.DisplayWizard("Select terrain to put grass on", typeof (GrassCreator), "Place Grass on Terrain");
}
void OnWizardCreate () {
if (!terrain) {
Debug.Log("You have not selected a terrain object");
return;
}
if (detailIndexToMassPlace >= terrain.terrainData.detailPrototypes.Length) {
Debug.Log("You have chosen a detail index which is higher than the number of detail prototypes in your detail libary. Indices starts at 0");
return;
}
if (splatTextureIndicesToAffect.Length > terrain.terrainData.splatPrototypes.Length) {
Debug.Log("You have selected more splat textures to paint on, than there are in your libary.");
return;
}
for (int i = 0; i < splatTextureIndicesToAffect.Length; i ++) {
if (splatTextureIndicesToAffect[i] >= terrain.terrainData.splatPrototypes.Length) {
Debug.Log("You have chosen a splat texture index which is higher than the number of splat prototypes in your splat libary. Indices starts at 0");
return;
}
}
if (detailCountPerDetailPixel > 16) {
Debug.Log("You have selected a non supported amount of details per detail pixel. Range is 0 to 16");
return;
}
int alphamapWidth = terrain.terrainData.alphamapWidth;
int alphamapHeight = terrain.terrainData.alphamapHeight;
int detailWidth = terrain.terrainData.detailResolution;
int detailHeight = detailWidth;
float resolutionDiffFactor = (float)alphamapWidth/detailWidth;
float[,,] splatmap = terrain.terrainData.GetAlphamaps(0,0,alphamapWidth,alphamapHeight);
int[,] newDetailLayer = new int[detailWidth,detailHeight];
//loop through splatTextures
for (int i = 0; i < splatTextureIndicesToAffect.Length; i++) {
//find where the texture is present
for (int j = 0; j < detailWidth; j++) {
for (int k = 0; k < detailHeight; k++) {
float alphaValue = splatmap[(int)(resolutionDiffFactor*j),(int)(resolutionDiffFactor*k),splatTextureIndicesToAffect[i]];
newDetailLayer[j,k] = (int)Mathf.Round(alphaValue * ((float)detailCountPerDetailPixel)) + newDetailLayer[j,k];
}
}
}
terrain.terrainData.SetDetailLayer(0,0,detailIndexToMassPlace,newDetailLayer);
}
void OnWizardUpdate ()
{
helpString = "Ready";
}
}
269984–9722–$grasscreator_131.cs (2.6 KB)
Works great! Thanks
I said something wrong:
It actually means exactly that. A setting of “1” does indeed place 1 on each resolution pixel and so forth. Must have counted wrong initially.
Hm, when I did extensive testing for my scripts, I found out that values about 9 give you odd results. Are you sure that 16 works well? I may have to go back and do some more testing.
Well, it works perfectly here ![]()
A value of 16 will give you 16 individual detail objects on each detail map pixel. 9 will give you… 9 ![]()
If you put in a number bigger than 16, it will still give you 16.
Maybe you put details on twice? A double amount of 8 will do, but 9 will go over the max. Maybe your loops takes you through the array twice, adding to what was already there the first time through?
Yes, of course. I do have a density multiplier there, that explains it.
Hi!
Thank you very much for this great script!
I got a problem with U3 though. Here is the log:
I am sorry if it’s one of my mistakes, I’m just non-programmer.
Doesn’t work ![]()
NullReferenceException: Object reference not set to an instance of an object
UnityEditor.ScriptableWizard.DisplayWizard (System.String title, System.Type klass, System.String createButtonName, System.String otherButtonName) (at C:/BuildAgent/work/6bc5f79e0a4296d6/Editor/MonoGenerated/Editor/ScriptableWizard.cs:106)
UnityEditor.ScriptableWizard.DisplayWizard (System.String title, System.Type klass, System.String createButtonName) (at C:/BuildAgent/work/6bc5f79e0a4296d6/Editor/MonoGenerated/Editor/ScriptableWizard.cs:96)
GrassCreator.createWizard () (at Assets/Standard Assets/grasscreator_131.cs:17)
The only recreation I can make of you problems, has to do with the name of the C# file. It HAS to be the same name as the Class. So I’m sure it’ll work if you call the file : “GrassCreator”
Right now it’s probably just “NewBehaviourScript” or something random of your own choice, which won’t work. So, rename the file to the above, and it will work fine
![]()
EDIT: It might even be “grasscreator_131.cs”, as for some strange reason, that is the name of the attached file ![]()
Change it to GrassCreator.cs! (if you do it directly in the editor, leave out the .cs)
Thanks for the great script! It works, but TOO WELL. It fills my scene with such a dense blanket of grass that it is unnavigable. Is there a way to make it it much less dense (while not affecting the density of other grass/plants/trees placed in scene)? Then this would be amazing…
Thanks!
Just looking at the script…try lowering this value:
detailCountPerDetailPixel
Hey, im trying out this script, and im wondering if I have to use a splat map for it to work. Or can I use it just like the mass place trees function? Also, im a bit confused at the different settings. Could someone explain it a bit more clearly?
Detail Index To Mass Place: Look at the detail objects you have added to the terrain, and count to the one you want to place (starting with 0);
Splat Texture Indices To Affect: This is the setting which control where to place the grass. If for instance you want to place grass everywhere you have a given texture, you just count which index this texture have (as with the above you start out at 0!). You can add more indexes, if for instance your grass areas are painted using more than one texture. Just add as many as you like.
Detail Count Per Detail Pixel: A terrain is divided into squares, and each square can hold up to 16 of each detail type. This setting simply defines how many grass planes you want to add at each section. This amount will be multiplied with the actual strength of the given texture, so if you only have 50% grass strength at some position, only 50% of the amount of planes will be placed.
Hope this script still works, haven’t tested in ages…
Hello. Seems interesting. Does this works on imported meshes as well? Thanks.
If you look at the code on this rather old script I think you will see that quite clearly that it doesn’t ![]()