Is `TerrainData.SetHeights()`permanent? If yes, how to make it non-permanent?

I am testing a C# script to change terrain data. Something as simple as this:

        float[,] heights = new float[513, 513];
        for (int i = 0; i < heights.GetLength(0); ++i)
        {
            for (int j = 0; j < heights.GetLength(1); ++j)
            {
                heights[i, j] += 0.2f;
            }
        }
        _terrainData.SetHeightsDelayLOD(0, 0, heights);

However, I found that after a test run, the terrain is also changed in the editor. I tried restarting, and it does not help. This raise my question: Are any changes performed by SetHeight() permanent? I can’t find anything describing this in documentation.

This leads to a second question: If I want the game to change a terrain within a level, but do not want the change to persist, what should I do? I can think of two:

  1. Somehow make non-permanent changes
  2. Somehow duplicate the terrain when level is loaded, and discard that at level complete.

If 1, how to do it? If 2, how feasible is it? Maybe duplicate the TerrainData and assign that to the Terrain object?

Terrain is an asset. That is to say, terrain data is serialised and saved as a file in your project folder - you can see it by browsing in Windows explorer. When you edit the terrain, you’re making changes to that file so, yes, those changes are permenant (the same is true if you edit materials).

The solution is as you’ve already proposed - to duplicate the asset and make changes to that instead.

You can do something like this:
terrain.terrainData = Object.Instantiate(terrain.terrainData);

Unity will instantiate a copy for you and the original will remain the same