- Home /
Terrain's SetHeights method misbehaving
Hello, I am trying to raise terrain height in controlled, consistent increments of 1 Unity unit.
Every time I attempt to raise my terrain by 1 unit, however, SetHeights instead raises it by 1 unit and some fraction of a unit.
My terrain height is set to 500. I use GetHeights to retrieve the height value of a coordinate and store it in float[0,0] height
.
To height
I add 0.002f
to the value, and then call SetHeights(coordinates, height)
.
Every time I call GetHeights, I log the float value retrieved, and every time I set the heights, I log the value of the float set.
It seems SetHeight is trying to set the proper float value, but upon getting the heightwe notice that some extra is put in there. What the log should be showing is increments of 0.002, 0.004, 0.006, etc...
Does anybody know why SetHeight is being inaccurate?
Answer by Eric5h5 · Mar 05, 2014 at 11:53 PM
Heights are actually 16-bit unsigned integers internally, where 1.0 = 65535. Therefore not all float values can be represented as heights, and they are rounded off to the nearest 1/65535.
Wait, why? Is that dumb? I'm not sure, but I feel like that's dumb.
Do you think that fact is going to cause problems if I need to incrementally raise and lower terrain over and over again?
The rounding will cause inaccuracies to pile up over time, right? I will eventually want to check if an area is flat, too, and other problems will arise due to the rounding, right?
It's not dumb to use ushorts for the height...that's what 16-bit raw heightmaps are. I'm not convinced that representing it as floats was the best decision, though, since that adds overhead of converting to/from ushort, and twice as much memory for the array. I guess it's "tidy" to represent heights as 0-1, but I think nobody would really have a problem with using 0-65535, considering the benefits of not needing float conversions and arrays.
I don't see that it would actually cause any problems, but you could do calculations as ushorts (or ints) and convert to float just to be sure.