- Home /
How can I get two different terrain instances to use different splat maps?
I have a terrain prefab. If I place more than one instance of this terrain in my scene (either using the editor or using a script) and then paint textures onto one of them (modifying the splat map), the same changes to the splat map appear on the other instance as well. See the picture below -- I painted the green 'S' on one instance of the landscape, and it appeared on both. How can I make these instances completely separate so that I can modify their splat maps separately?
Note that I already tried giving them different TerrainDatas, by script. That allowed me to change their height maps separately, but not their splat maps.
Answer by einWikinger · Oct 28, 2015 at 09:46 AM
I just wrote a complete deep-copying helper as I had to duplicate a source terrain into distinct copies:
https://gist.github.com/zsoi/c965ff38938cd126f00d
This way copying a terrain is as easy as:
newTerrain.terrainData = ZS.Tools.TerrainDataCloner.Clone(sourceTerrain.terrainData);
Thanks for this @einWikinger. Just fixed a bug in your script about treePrototypes and it's all good. $$anonymous$$ade my day!
Answer by Logopolis · Mar 03, 2015 at 12:31 AM
In case anyone else has this problem in the future, here's the solution I found. First, I instantiated the terrain:
terrainPatches[x,z] = (Terrain) Instantiate(terrainPrefab, new Vector3(0, 0, 0), Quaternion.identity);
Then, I needed to create a new TerrainData instance from scratch. It didn't work if I instantiated the TerrainData instance from a prefab -- they would all share the same splat maps. Instead, I had to create each TerrainData from scratch, fill in its attributes, and create the array of SplatPrototypes for each one. Here's the code I'm using, that solved the problem:
terrainPatches[x,z].terrainData = new TerrainData();
terrainPatches[x,z].terrainData.heightmapResolution = 129;
terrainPatches[x,z].terrainData.size = new Vector3(200,80,200);
terrainPatches[x,z].terrainData.alphamapResolution = 128;
terrainPatches[x,z].terrainData.baseMapResolution = 256;
terrainPatches[x,z].terrainData.SetDetailResolution(256, 8);
SplatPrototype[] splatPrototypes = new SplatPrototype[10];
for (int i = 0; i < 10; i++) {
splatPrototypes[i] = new SplatPrototype();
splatPrototypes[i].tileOffset = new Vector2(0,0);
splatPrototypes[i].tileSize = new Vector2(20,20);
switch (i) {
case 0: splatPrototypes[i].texture = terrainTexture0; splatPrototypes[i].normalMap = rockNormalMap; break;
case 1: splatPrototypes[i].texture = terrainTexture1; break;
case 2: splatPrototypes[i].texture = terrainTexture2; break;
case 3: splatPrototypes[i].texture = terrainTexture3; splatPrototypes[i].normalMap = grassNormalMap; break;
case 4: splatPrototypes[i].texture = terrainTexture4; splatPrototypes[i].normalMap = rockNormalMap; break;
case 5: splatPrototypes[i].texture = terrainTexture5; splatPrototypes[i].normalMap = rockNormalMap; break;
case 6: splatPrototypes[i].texture = terrainTexture6; break;
case 7: splatPrototypes[i].texture = terrainTexture7; break;
case 8: splatPrototypes[i].texture = terrainTexture8; break;
case 9: splatPrototypes[i].texture = terrainTexture9; break;
}
}
terrainPatches[x,z].terrainData.splatPrototypes = splatPrototypes;