How to modify a Terrain at runtime and get back to original Terrain on exit?

Hello,

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!

Have you got an idea?
Thanks in advance! :slight_smile:

99542-after-quitting.png

EDIT:

I used this awesome script to safely clone my terrain: Helper to deep-copy a TerrainData object in Unity3D · GitHub

Just had to write this:

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 :smiley:

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 :stuck_out_tongue_winking_eye:

Edit:

GetAlphamaps(int x, int y, int width, int height);

Use this to access all the splat maps