Search Unity

Setting full terrain texture (image) from script not working

Discussion in 'World Building' started by pdhr, Aug 23, 2019.

  1. pdhr

    pdhr

    Joined:
    May 13, 2019
    Posts:
    25
    Hi all,

    I have an issue with the Unity terrain, and I hope you can help with that.

    I am setting the terrain texture (which is an image) from a script, which I want to span the entire terrain tile. This worked fine (as you can see in this thread) while I was on Unity 2018.3 (I believe).

    However, somewhere since updating to 2019.1 or 2019.2, it no longer sets the texture. Instead, I get the grey checkerboard. However, the texture is loaded into the Terrain object's TerrainLayer, and I can then 'paint' it with the brush, but it should be set automatically like before.

    Do you have any idea what changed or how to fix this? I am currently on 2019.2.1f1.

    See the code below where I set it:

    Code (CSharp):
    1.  
    2.         {
    3.             for (int j = 0; j < 2; ++j) //config.NumElevationTileRows
    4.             {
    5.                 for (int i = 0; i < 2; ++i) //config.NumElevationTileColumns
    6.                 {
    7.                     id = i + j * (config.NumElevationTileColumns);
    8.                     TerrainData data = new TerrainData();
    9.                     tiles[id] = Terrain.CreateTerrainGameObject(data);
    10.  
    11.                     tiles[id].name = String.Format("Terrain_{0}x{1}", i, j);
    12.                     tiles[id].tag = "Terrain";
    13.                     tiles[id].layer = TerrainUtils.LayerTerrain;
    14.                     tiles[id].transform.position = center_offset + new Vector3((float)config.GetStartPositionX(id), 0, (float)config.GetStartPositionZ(id));
    15.                     tiles[id].transform.SetParent(terrainRoot.transform);
    16.                     tiles[id].isStatic = true;
    17.  
    18.                     tiles[id].GetComponent<Terrain>().drawInstanced = true;
    19.                     SetElevationFromTileFile(config, tiles[id], (config.NumElevationTileRows - j - 1) * config.NumElevationTileColumns + i);
    20.                     tiles[id].GetComponent<Terrain>().heightmapPixelError = heightmapPixelError;
    21.                     SetTerrainImagery(config, data, id);
    22.                     tiles[id].GetComponent<Terrain>().Flush();
    23.                 }
    24.                 Debug.LogFormat("Processed tile row {0}", j);
    25.             }
    26.         }
    27.  
    28.         private static void SetTerrainImagery(TileConfiguration config, TerrainData terrainData, int id)
    29.         {
    30.             // Initialise terrainLayer
    31.             float tilesize = (float)config.ElevationTileDimension;
    32.             TerrainLayer[] terrainLayers = new TerrainLayer[1];
    33.             terrainLayers[0] = new TerrainLayer();
    34.             terrainLayers[0].tileOffset = new Vector2();
    35.             terrainLayers[0].tileSize = new Vector2(tilesize, tilesize);
    36.  
    37.             // Set Ortho
    38.             Texture2D ortho = (Texture2D)(AssetDatabase.LoadAssetAtPath(String.Format("{0}\\{1}.png", TerrainUtils.ImageryPath, id), typeof(Texture2D)));
    39.             ortho.filterMode = FilterMode.Bilinear;
    40.             ortho.wrapMode = TextureWrapMode.Clamp;
    41.          
    42.             terrainLayers[0].diffuseTexture = ortho;
    43.  
    44.             // Assign terrainLayer to Terrain
    45.             terrainData.terrainLayers = terrainLayers;
    46.         }
    See this image for what I mean:
     
    Skaltum likes this.
  2. Skaltum

    Skaltum

    Joined:
    Nov 1, 2013
    Posts:
    28
    I have this problem as well.

    The workaround is to manually set the alpha map to all ones.

    Code (CSharp):
    1.  
    2. var layers = new TerrainLayer[] { yourTerrainLayer };
    3. terrainData.terrainLayers = layers;
    4. var alpha1 = new float[terrainData.alphamapResolution,terrainData.alphamapResolution, 1];
    5. for (int i = 0; i < alpha1.GetLength(0); i++)
    6. {
    7.     for (int j = 0; j < alpha1.GetLength(1); j++)
    8.     {
    9.         for (int k = 0; k < alpha1.GetLength(2); k++)
    10.         {
    11.             alpha1[i, j, k] = 1;
    12.         }
    13.     }
    14. }
    15.  
    16. terrainData.SetAlphamaps(0,0, alpha1);
    17.  
    It's not pretty.
     
    pdhr likes this.
  3. pdhr

    pdhr

    Joined:
    May 13, 2019
    Posts:
    25
    Ah now that you say this, it seems like a quite obvious fix. Thanks a ton!

    However, as you say, it's certainly not pretty..
    It would be nicer for Unity to revert back to the old behaviour of fully showing the texture if there's only one terrainLayer assigned to the terrain. I believe that behaviour is even explicitly stated in the docs, so that would actually make this a bug (unintended behaviour). Fingers crossed it'll be fixed.