- Home /
How do I use Terrain SetHeights and GetHeights
I have a small scene, consisting of a 128x128x128 terrain. Those are the dimensions and height. All I want to do is be able to modify the terrain height in a sensible and clear way.
I execute this code, every time you press "T".
// Get the height at 0,0
float height = Terrain.activeTerrain.terrainData.GetHeight(0, 0);
Debug.Log(height);
// Increase it by .001
Terrain.activeTerrain.terrainData.SetHeights(0,0,new[,]{{height + 0.001f}});
// Print the new height
height = Terrain.activeTerrain.terrainData.GetHeight(0, 0); Debug.Log(height);
Here is the debug output for the first height increase:
0 (the initial height, which is correct)
0.1289141 (? I increased it by .001...)???
The second time I do this, I get:
.1289141 ok correct, I guess...that was the previous value
16.62992 -??? What the heck!? How/WHY did it jump from .128 to 16.62
The unity documentation is pretty much useless on this matter. If my terrain height has a max height of 100 meters, I should be able to increase the height at a given point by 0.01 to raise it a meter, right? Is the height increase being treated as a multiplier??
Can someone shed some light on this situation?
Answer by Eric5h5 · Dec 10, 2011 at 03:13 AM
Heights are actually stored as 16-bit integers; not sure why they decided to use floats for GetHeights/SetHeights, since there's a conversion process when reading and writing.
Interesting. In working with this, it appears GetHeights returns the actual world height, but SetHeights expects a percent of the height (which as you said, gets stored as in int).
I'll have to work out the math and confirm this :)
No, GetHeights returns heightmap values. Those are unrelated to world height. It's not a percentage, rather it's a value ranging from 0-65535 (represented as a float from 0-1).
This is what confuses me. In my original post, GetHeights() reported the height at 0,0 as 0. So I increased it by .001. When I checked the value after that, GetHeights reported .128xxxx. Weird. So I increase it by .001 again.
The next time I checked the value it was 16.xxxx. This is why it seems like GetHeights reports world height.
As I mentioned, the actual values are 16-bit integers. If you store .001, you're not going to get .001 back, you're going to get whatever the closest 16-bit integer equivalent is.
Not to belabor this (and thanks for your patience Eric5h5), but would that account for the increase from .128xxx to 16.xxx, just by increasing the set height value by .001? $$anonymous$$aybe I'm just not grasping something.
The height was originally at 0. I increased it to 0.001, and the return getheights value was .128.
I increased it another .001, and getheights return 16! That seems like a huge jump. I went back, and stored the heights for the entire terrain in an array of floats. I then increased the ARRAY value by .001 each time, ins$$anonymous$$d of increasing the return value from GEtHeights by .001, and that seemed to work as expected. Regardless, I think I have something to go on, and I'll keep at it, and look back over my methods. Thanks!
Answer by Bunny83 · Dec 10, 2011 at 12:42 PM
It's quite simple. I've done a small test like you did. This are the results:
GetHeight returns the height value in the range [0.0f, Terrain Height]
GetHeights returns the height values in the range of [0.0f,1.0f]
SetHeights expect the height values in the range of [0.0f,1.0f].
So when using GetHeight you have to manually divide the value by the Terrain.activeTerrain.terrainData.size.y
which is the configured height ("Terrain Height") of the terrain.
The behaviour of GetHeight seems a bit strange and does not return what you would expect. This might be a bug / might be a feature, however without a proper documentation it's more likely a bug.
This explanation makes sense (unlike the API implementation). And even more bizarre...there is no SetHeight function to match GetHeight.
This was my experience too. From a terrain with height of 200:
GetHeight: 62.65641 GetHeights: 0.3132821 (normalized, or same as if terrain height was 1)
0.3132821 * 200 = 62.65641
Answer by fenderrex · May 14, 2020 at 07:39 AM
SO AFTER SOME DIGGING and seeing this solution called simple! I got this snip working... here how I fixed my misconceptions!! I was importing via 3rd party brush so scale is hard to tell at the moment my problem was I set the scale/Resolution after setting terrainData.size this scaled along the x z axis and looked flat
TerrainData _TerrainData = new TerrainData();
TerrainObj.transform.position = JsonUtility.FromJson<NVector3>(weaponDatabase.position).V3();
_TerrainData.heightmapResolution = weaponDatabase.scale;
_TerrainData.baseMapResolution = 64;
Debug.Log("height scale");
Debug.Log(_TerrainData.heightmapScale);// = 1000;
// _TerrainData. = new Vector3(2,1000,2);
Debug.Log(_TerrainData.size.y);
_TerrainData.SetDetailResolution(2049, 2049);
float[,] heighty = { { 1.0f, 0.23f }, { 0.10f, 0.40f } };
_TerrainData.SetHeights(0, 0, heighty);
_TerrainData.size = new Vector3(4000, 1000, 4000);
Your answer
Follow this Question
Related Questions
terrainData SetHeights/GetHeights? 1 Answer
Process heavy issues 0 Answers
Need help with terrainData.GetHeight 1 Answer
Terrain's SetHeights method misbehaving 1 Answer
Make a simple tree 1 Answer