Access TerrainData data

I read in the documentation that the Terrain data class stores heightmaps, detail mesh positions, tree instances…

How do I access the detail mesh positions ?

And is it possible to get the positions from all the instantiated trees ?

Claus Bjerre

Hi Claus,

unfortunatly I can’t answer your question also.

At least, it’s possible to read height informations with
function GetHeights (xBase : int, yBase : int, width : int, height : int) : float[,]

and set height informations with
function SetHeights (xBase : int, yBase : int, heights : float[,]) : void

But the script docu let’s us completly alone with the data model it’s based on.
There helps only testing, testing, testing …

That’s really poor !

And there’s defenitly no script interface for terrain objects and tree instances which let you modify them while runtime. At least it should be possible to delete a tree or terrain object by script while runtime.

All data seem to be stored in the Terrain.Asset, which contains the Light and Splat maps. But there’s no script interface to access these data.

I read a lot in the forum with the hope to find informations to this topic. The result is almost zero.

Finally, a sufficent docu of and a useful script interface to terrain data misses to work with the generated terrain data while runtime.

If you found out more, please let me know.

1 Like

This returns a rank 2 float array starting at position xBase, yBase in the heightmap, with the specified width and height. Each item in the array ranges from 0.0 to 1.0, with 0 being the lowest height and 1 being the highest.

This sets the heightmap data starting at position xBase, yBase in the heightmap, using a rank 2 float array.

For example, say you have a terrain, and you want to read it all into an array and then perturb the heightmap randomly, and then set the terrain to this new data.

var terrain : Terrain;

function Start () {
    var xRes = terrain.terrainData.heightmapWidth;
    var yRes = terrain.terrainData.heightmapHeight;
    var heights = terrain.terrainData.GetHeights(0, 0, xRes, yRes);

    for (y = 0; y < yRes; y++) {
        for (x = 0; x < xRes; x++) {
            heights[x,y] = (Random.Range(0.0, 1.0) + heights[x,y]) * .5; 
        }
    }

    terrain.terrainData.SetHeights(0, 0, heights);
}

If you only wanted to read some of the heightmap data instead of the whole thing, then do something like

var heights = terrain.terrainData.GetHeights(50, 75, 40, 40);

which would return a 40x40 square starting at position 50,75 of the heightmap. This example would only work if the terrain’s heightmap resolution is equal to or greater than 129x129.

One possible catch to using this stuff is that I have no idea how to make a new built-in array with more than one dimension in Javascript. Obviously Javascript handles it just fine, but I’ve only been able to make such an array using type inference like this, and not from scratch. You’d think you’d be able to do

var heights = new float[513,513];

or something, but that doesn’t work. This is possible in C# but I can’t remember the syntax offhand.

Officially. :wink: The terrain tools are actually scripts (if you look at the Terrain component in the Inspector, you see it says “Terrain (Script)”, so it’s possible.

–Eric

Hi Eric, hi claus,

Eric, thanks for your hints to the terrain functions. I experimented a bit with them. That’s what I found out:

First some general things. If you know more about it, let me know, please.

(1) Creation

You can’t create a terrain by script while runtime. The “New Terrain” Prefab is not a normal Prefab (you can’t add any components to it). There’s no documentation of the terrain wizzard scripts.

/Users/unity-build/Desktop/automatic-build-2/unity/Editor/Mono/TerrainEditor/TerrainWizards.cs

The terrain origin is always (0, 0, 0). Transform, scale and rotation are not modifiable.

(2) Terrain - Set Resolution

Manual:

“If you would like a differently sized Terrain, choose Terrain->Set Resolution from the menu bar. There are a number of settings that related to Terrain size which you can change from this dialog.”

Terrain width, height, length

Obviously you can set the paramters in world coordinates of a cube, which defines the terrain width, height and length. You can’t change this parameters while runtime by script.

Width (TerrainData.size.x) and length (TerrainData.size.z) are connected to the heightmap resolution. Means how many samples per meter in world coordinates. Height (TerrainData.size.y) is defined between 0.0 and 1.0. Means 1.0 is aequivalent to height in world coordinates.

heightmap resolution

The minimum value is 33. If you set the height map resolution to e.g. 33, you can modify 32 heigtht samples and the TerrainData.heightmapWidth and as well the TerrainData.heightmapHeight is 33.

To calculate the (x,z) position of a terrain sample in world coordinates use:

(x in m * TerrainData.heightmapWidth in samples / TerrainData.size.x in m , z in m * TerrainData.heightmapWidth in samples / TerrainData.size.z in m)

To calculate the y position of a terrain sample in world coordinates use:

y * 1 / TerrainData.size.y in m

You can’t change heightmap resolution while runtime by script.

Detail Resolution

The minimum value is 32.

Control Texture Resolution

The minimum value is 16.

Base Texture Resolution

The minimum value is 16.

Depending on this, I wrote three example scripts. Create a terrain and attach
‘ModifyTerrain’ script to it. Than attach ‘ModifyTerrainHeight’ or 'WrapMeshToTerrain sript to it… First one delivers some comfort functions to work with terrain hight data. Second one is a example for modifying height data. Third one derives a mesh from the terrain data. If you found out more, give me some feed back, please.

Thanks Rob

See the attached scripts.

71468–2677–$wrapmeshtoterrain_114.js (3.93 KB)
71468–2678–$modifyterrainheight_209.js (3.08 KB)
71468–2679–$modifyterraindata_197.js (6.7 KB)

Ups ! Forgot. See also this example.

http://forum.unity3d.com//viewtopic.php?t=10659

Last example was wrong:

z in m * TerrainData.heightmapWidth ← should be z in m * TerrainData.heightmapHeight