TerrainData.GetDetailLayer()

I am trying to get whether or not there is grass on a given location on the terrain. I did a test of GetDetailLayer() comparing a 2500x2500 patch underneath an object on top of grass and one with no grass and in both cases the entire 2D array returned is filled with 0s. If this is the correct behavior for this call (which makes no sense to me given that I’m STARING at the grass under the grass objects) then any idea on how I can get this information from the terrain?

void Start () {
	int[,] retVal;
	Terrain myTerrain;
	TerrainData myTData;
	int xPos = (int)this.transform.position.x;
	int zPos = (int)this.transform.position.z;
	int xDir = 2500;
	int zDir = 2500;
	int found = 0;
	
	myTerrain = (Terrain)FindObjectOfType(typeof(Terrain));
	Debug.Log("terrain name " + myTerrain.name);
	myTData = myTerrain.terrainData;
	retVal = myTData.GetDetailLayer (xPos, zPos, xDir, zDir, 0);
	Debug.Log("has decal " + this.name + " x:x " + this.transform.position.x + ":" + xPos + " z:z " + this.transform.position.z + ":" + zPos);
	for(int i = 0; i < xDir; i++)
	{
		for(int j = 0; j < zDir; j++)
		{
			if( retVal[i,j] != 0 )
			{
				found++;
				Debug.Log(i + "," + j + "	" + retVal[i,j]);
			}
		}
	}
	Debug.Log("found = " + found);
}

Maybe this will help someone:

int detailWidth = _SourceTerrain.terrainData.detailWidth;
int detailHeight = _SourceTerrain.terrainData.detailHeight;
int[,] detailLayer = _SourceTerrain.terrainData.GetDetailLayer(0, 0, detailWidth, detailHeight, 0); // Get the detail data for the first prototype, for the entire terrain.

// Detailayer is a 2d array the size of the heightmap (width x height). The return value of each element [z,x] element is an int from 0-16, which
// represent the number of details placed at that location. detailLayer[z,x]

So, if you had a terrain that was 512x512, and it had two details: Green grass (#0) and flowers (#1), and you wanted the amounts for flowers for the entire terrain, you do this:

int[,] detailLayer = _SourceTerrain.terrainData.GetDetailLayer(0, 0, de, detailHeight, 1); // 1 is the flower prototype index

detailLayer is a 2d int array, of [height, width] in this case. The int it returns is the amount of flowers placed at that location on the terrain. NOTE that when reading and setting the values for this detail layer, Z is the first element, and X is the second.

In the inspector, you set target strength at a float value form 0 to 1. Internally, unity stores a value from 0 to 16. This is the number of flowers it places at this location.
The only thing I could get opacity to do in the inspector was, if set to zero, no details were placed there.

So, if you want to set the number of flowers at this location to 8, just set it to 8. It would be the same as painting flowers there with the strength setting set to .5 (8 = 1/2 of 16). So, if you wanted to set the details at z=5, x=10 to 8 flowers, you would do this:

detailLayer[5,10] = 8; // near the bottom left hand corner of the terrain
_SourceTerrain.terrainData.SetDetailLayer(0,0,0,detailLayer);