- Home /
Terrain artifacts after binary serialization
Hi,
Im working towards serialising my Terrain, and from what I can gather I have to create a byte[] out of Getheights and then convert it back to Setheights to reimplement.
When testing a basic implementation of that process I run into many artefacts and much unpleasantness.
Im fairly sure its something to do with the way im reimplementing the byte[] into Setheights, as altering the division value changes the amplitude of the distortion, however ive hit a wall with how to resolve the situation.
Any help would be greatly appreciated.
An example of the distortion:
Happy
Not happy.
using UnityEngine;
using System.Collections;
public class terrainSTATE : MonoBehaviour
{
public bool getdat;
public bool setdat;
byte[] Bytes;
void Update ()
{
if (getdat) {
GetData ();
}
if (setdat) {
SetData ();
}
}
void GetData ()
{
TerrainData TD = GetComponent<Terrain> ().terrainData;
float[,] heights = TD.GetHeights (0, 0, 512, 512);
Bytes = new byte[263169];
int i = 0;
for (int x = 0; x < 512; ++x) {
for (int y = 0; y < 512; ++y) {
Bytes [i] = (byte)Mathf.Round (Mathf.Lerp (0, 65535, heights [x, y]));
i++;
}
}
getdat = !getdat;
}
void SetData ()
{
TerrainData TD = GetComponent<Terrain> ().terrainData;
int heightmapWidth = TD.heightmapWidth;
int heightmapHeight = TD.heightmapHeight;
float[,] heightmap = new float[heightmapWidth, heightmapHeight];
int i = 0;
for (int x = 0; x < 512; ++x) {
for (int y = 0; y < 512; ++y) {
heightmap [x, y] = Bytes [i] / 512f;
i++;
}
}
TD.SetHeights (0, 0, heightmap);
setdat = !setdat;
}
}
Answer by whydoidoit · Aug 08, 2013 at 08:55 PM
A byte can only hold a value between 0 and 255 so I'm a bit confused about:
Your Lerp is between 0 and 65535
You are dividing the result by 512
I would have thought:
Bytes[i] = (byte)Mathf.RoundToInt(255 * heights[x,y]);
heightmap [x,y] = Bytes[i] / 255f;
You could of course just serialize the floats, or are you trying to keep it compressed? It will be "steppy" if you round it to bytes due to the reduction in precision.
That works as described thanks. The confusion came from me stitching bits together from unrelated sources and not having the understanding to modify it correctly.
Actually im just experimenting with methods of saving the terrain using your Unity Serializer. I figured pulling Getheights into a byte[] on a holder script then serialising that was the most efficient way to do it.
Seeing how steppy the output is though floats would appear the best direction to go, even though i assume performance wise thats going to be a bit of a hit.
Thanks for your help.
Well floats take 4 bytes each, compared to 1 byte for the way you have it. But I would go the "float" route myself.
Hmm, storing as a float[] (or generic list) does work, however though Unity Serializer functions correctly over assembly reloads during runtime, stopping and replaying seems to wipe all save data. This behaviour only happens when this array is serialised, and does not happen with other arrays/lists of type.
Edit: On further testing with different length generic list of floats i find the following behaviour.
A length of >48975 no saved data persists across loads.
<=48975 && >24423 only 1 saved entry will persist.
<=24423 2 saves will persist.
<=12147 will allow 4 saves...
Any idea why this might be? Am i missing something?
$$anonymous$$y apologies for taking the topic well out of the scope of the original question.