This is a very naive approach to the wonderfull world of Unity3D Terrain System.
I played around with it for a long time, did some cool things with it, like on-the-fly bomb craters via script and stuff.
It actually is time now to do this a bit more focused, since I am planing to use it in my game Tanks with Legs. For doing so, I started a laboratory session with Unity3D 2019.
First thing I want and need to do : Take a Mesh and put it on the terrain surface like a coat. I need this for my procedural level generator streetmap generator to make the streets or paths align to the height of the terrain.
But I ran into some problems while doing so and noticed I have to fresh up on a few things. I will do this very slowly and document it here.
Put a grid on the terrain
First thing I want to do is to put a grid of sphers on the terrain, on the same height as their world position on the terrain.
I setup a new GameObject and put a script on it which I named TerrainGridder.
First thing I need to know is which terrain to use, which is done by a public Terrain field so it can be assigned in the inspector.
Now I need to get the pivot world location of the terrain and then the dimensions of the terrain. Since the dimensions in the transform of a terrain is (1/1/1), this is not really usefull.
On a normal GameObject you would use the bounds of the Renderer Component, but since a terrain has no renderer (at least not by default or as component), you can use the size field of the terrainData field of the terrain. This field holds a vector with the dimensions of the terrain in worldScale.
With the method getHeight of the terrainData object of the terrain I can get easily the height of the terrain at a (x/z) world position.
So after using this code :
for (int y = 0; y < gridSize; y++)
{
float ypos = (terrainDimensionsInWorldScale.y / gridSize) * y;
for (int x = 0; x < gridSize; x++)
{
GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
float xpos = (terrainDimensionsInWorldScale.x / gridSize) * x;
sphere.transform.position = new Vector3(xpos, terrainToGrid.terrainData.GetHeight((int)xpos, (int)ypos), ypos);
}
}
I have this grid on the terrain :

But if I change the height of the spheres using the retrieved y height with the terrainData method, it is nor working as excepted :

So what am I doing wrong here ? Let me investigate.
So first of all, it seems that I should use terrain.SampleHeight and not terrain.terrainData.GetHeight.
So with this code :
for (int y = 0; y < gridSize; y++)
{
float ypos = (terrainDimensionsInWorldScale.z / gridSize) * y;
for (int x = 0; x < gridSize; x++)
{
GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
float xpos = (terrainDimensionsInWorldScale.x / gridSize) * x;
sphere.transform.position = new Vector3(xpos, terrainToGrid.SampleHeight(new Vector3(xpos,0,ypos)), ypos);
}
}
I get the result I wanted as first step.

The grid of spheres is now perfectly aligned on the y-axis according to the terrain height. With this I can start part two of the TerrainGridder : Taking a mesh and changing the height of its vertices to the height of the terrain.