I’m trying to rotate a terrain in runtime, then I want the terrain to get back to its original rotation when I quit the app.
I have basically this algorithm:
Copy (“clone”) the Terrain Data
Rotate that copy
When quitting, the copy is automatically destroyed, so the terrain should get back to its original data.
The following code implements this algorithm:
using UnityEngine;
public class RotateTerrain : MonoBehaviour
{
[SerializeField]
private Terrain terrain;
void Start()
{
WorkOnNewCopy();
// Now we can safely modify our terrain... Can we?
TerrainRotate(terrain, degrees: 90);
}
void WorkOnNewCopy()
{
TerrainData backup_terrainData = terrain.terrainData;
backup_terrainData.name = terrain.terrainData.name + "_tmp";
backup_terrainData = Instantiate(backup_terrainData);
terrain.terrainData = backup_terrainData;
terrain.GetComponent<TerrainCollider>().terrainData = backup_terrainData;
terrain.Flush();
}
void TerrainRotate(Terrain terrain, float degrees)
{
// Super-secret code
}
}
It’s almost working: when I quit the app (or editor), I find myself with a weird mix between the original terrain, and the modified terrain.
I’ve attached some pictures (before rotation, and after rotation and quitting): everything seems to be back, except the ground texture (splat map).
I feel close to the solution!
terrain.terrainData = TerrainDataCloner.Clone(terrain.terrainData);
terrain.GetComponent<TerrainCollider>().terrainData = terrain.terrainData; // Don't forget to update the TerrainCollider as well
After this, the rotation works perfectly, and it reverts back automatically when I quit.
Just what I wanted!
PREVIOUS ANSWER:
Hi Menyus777,
Yes I use 6 textures for my terrain. Maybe it could be this?
I just need to rotate all of my splatmaps?
And yes, the “super-secret” comment was more of a joke, since I mostly use source code from Terrain Rotator plugin, which is free
I just wanted to show the algorithm and I wanted it clean and understandable so the rotation code was unrelated to me!
But, part of my code is about splatmaps, and I have the feeling it should already rotate ALL the splatmaps, so is it a bug?
// alpha layer (texture splatmap) rotation
dw = terrain.terrainData.alphamapWidth;
dh = terrain.terrainData.alphamapHeight;
int dz = terrain.terrainData.alphamapLayers;
float alphaMiddle = (terrain.terrainData.alphamapResolution) / 2.0f; // pivot at middle
float[,,] newAlphaMap = new float[dw, dh, dz];
for (int z = 0; z < dz; z++)
{
for (int y = 0; y < dh; y++)
{
for (int x = 0; x < dw; x++)
{
cs = Mathf.Cos(angleRad);
sn = Mathf.Sin(angleRad);
nx = (int)((x - alphaMiddle) * cs - (y - alphaMiddle) * sn + alphaMiddle);
ny = (int)((x - alphaMiddle) * sn + (y - alphaMiddle) * cs + alphaMiddle);
if (nx < 0) nx = 0;
if (nx > dw - 1) nx = dw - 1;
if (ny < 0) ny = 0;
if (ny > dh - 1) ny = dh - 1;
newAlphaMap[x, y, z] = origAlphaMap[nx, ny, z];
} // for x
} // for y
} // for z
Modifying TerrainData at runtime via script cannot be undone except with temp saves, your terrain fault is the splatmap, probably u are using more then one splat map because you use more then 4 textures for your terrain 1 splatmap can hold 4 textures, u sure u are roating all of them?
Also when i tried roating my splatmap i member that the result was not accurate so i find another solution.
And damn bro Terrain rotation is not that top secret
Edit:
GetAlphamaps(int x, int y, int width, int height);