Skip to content

Instantly share code, notes, and snippets.

@andrew-raphael-lukasik
Last active December 28, 2022 23:30
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrew-raphael-lukasik/d2903247b3f9c94e6faa9c042d9f0460 to your computer and use it in GitHub Desktop.
Save andrew-raphael-lukasik/d2903247b3f9c94e6faa9c042d9f0460 to your computer and use it in GitHub Desktop.
UnityEngine, Fix Terrain Seams
// src*: https://gist.github.com/andrew-raphael-lukasik/d2903247b3f9c94e6faa9c042d9f0460/

#if UNITY_EDITOR
[UnityEditor.MenuItem( "Tools/Fix All Terrain Seams" )]
static void FixAllSeams () { FixTerrains( Object.FindObjectsOfType<Terrain>() ); }
#endif

static void FixTerrains ( Terrain[] terrains )
{
    foreach( var terrain in terrains ) FixTerrainsTopBottom( terrain );//Z axis pass
    foreach( var terrain in terrains ) FixTerrainsLeftRight( terrain );//X axis pass
    //note: passes are separated by axis to evade undesired complexities at corners
    //        (when corner shares more than one neighbor).
}

static void FixTerrainsTopBottom ( Terrain terrain )
{
    #if UNITY_EDITOR
    if( UnityEditor.EditorApplication.isPlaying==false ) UnityEditor.Undo.RegisterCompleteObjectUndo( terrain.terrainData , "Fix Seams" );
    #endif
    int length = terrain.terrainData.heightmapResolution;
    int last = length-1;
    Terrain TOP = terrain.topNeighbor;
    Terrain BOTTOM = terrain.bottomNeighbor;
    float[,] heights = terrain.terrainData.GetHeights( 0 , 0 , length , length );
    int numSteps = length / 20;
    if( TOP!=null )
    {
        float[,] topHeights = TOP.terrainData.GetHeights( 0 , 0 , length , length );
        for( int x=0 ; x<length ; x++ )
        {
            float me = heights[ last , x ];
            float other = topHeights[ 0 , x ];
            if( me >= other ) { continue; }
            float height = other;
            for( int step=0 ; step<numSteps ; step++ )
            {
                //recursive lerp function:
                height = Mathf.Lerp(
                    height ,
                    heights[ last-step , x ] ,
                    (float)step / (float)numSteps
                );
                heights[ last-step , x ] = height;
            }
        }
    }
    if( BOTTOM!=null )
    {
        float[,] bottomHeights = BOTTOM.terrainData.GetHeights( 0 , 0 , length , length );
        for( int x=0 ; x<length ; x++ )
        {
            float me = heights[ 0 , x ];
            float other = bottomHeights[ last , x ];
            if( me >= other ) { continue; }
            float height = other;
            for( int step=0 ; step<numSteps ; step++ )
            {
                //recursive lerp function:
                height = Mathf.Lerp(
                    height ,
                    heights[ step , x ] ,
                    (float)step / (float)numSteps
                );
                heights[ step , x ] = height;
            }
        }
    }
    terrain.terrainData.SetHeights( 0 , 0 , heights );
}
static void FixTerrainsLeftRight ( Terrain terrain )
{
    #if UNITY_EDITOR
    if( UnityEditor.EditorApplication.isPlaying==false ) UnityEditor.Undo.RegisterCompleteObjectUndo( terrain.terrainData , "Fix Seams" );
    #endif
    int length = terrain.terrainData.heightmapResolution;
    int last = length-1;
    Terrain RIGHT = terrain.rightNeighbor;
    Terrain LEFT = terrain.leftNeighbor;
    float[,] heights = terrain.terrainData.GetHeights( 0 , 0 , length , length );
    int numSteps = length / 20;
    if( RIGHT!=null )
    {
        float[,] rightHeights = RIGHT.terrainData.GetHeights( 0 , 0 , length , length );
        for( int y=0 ; y<length ; y++ )
        {
            float me = heights[ y , last ];
            float other = rightHeights[ y , 0 ];
            if( me >= other ) { continue; }
            float height = other;
            for( int step=0 ; step<numSteps ; step++ )
            {
                //recursive lerp function:
                height = Mathf.Lerp(
                    height ,
                    heights[ y , last-step ] ,
                    (float)step / (float)numSteps
                );
                heights[ y , last-step ] = height;
            }
        }
    }
    if( LEFT!=null )
    {
        float[,] leftHeights = LEFT.terrainData.GetHeights( 0 , 0 , length , length );
        for( int y=0 ; y<length ; y++ )
        {
            float me = heights[ y , 0 ];
            float other = leftHeights[ y , last ];
            if( me >= other ) { continue; }
            float height = other;
            for( int step=0 ; step<numSteps ; step++ )
            {
                //recursive lerp function:
                height = Mathf.Lerp(
                    height ,
                    heights[ y , step ] ,
                    (float)step / (float)numSteps
                );
                heights[ y , step ] = height;
            }
        }
    }
    terrain.terrainData.SetHeights( 0 , 0 , heights );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment