Search Unity

  1. We are migrating the Unity Forums to Unity Discussions. On July 12, the Unity Forums will become read-only.

    Please, do not make any changes to your username or email addresses at id.unity.com during this transition time.

    It's still possible to reply to existing private message conversations during the migration, but any new replies you post will be missing after the main migration is complete. We'll do our best to migrate these messages in a follow-up step.

    On July 15, Unity Discussions will become read-only until July 18, when the new design and the migrated forum contents will go live.


    Read our full announcement for more information and let us know if you have any questions.

Question Footstep blending across one material?

Discussion in 'Audio & Video' started by softdist0rtion, Nov 15, 2023.

  1. softdist0rtion

    softdist0rtion

    Joined:
    Nov 10, 2023
    Posts:
    2
    So I've heard about blending footsteps across different terrains with a script, but can one achieve this at a texture level?

    I have one terrain material that is composed of three blended textures with alphas and heightmaps. Would it be possible to apply the same logic (TerrainData.GetAlphamaps) with something like Texture2D.GetPixelData and comparing the alpha values of the three textures to determine the footstep material?

    I'm very new to Unity and scripting so I thought I would ask here before investing any more time in it.
     
  2. SeventhString

    SeventhString

    Unity Technologies

    Joined:
    Jan 12, 2023
    Posts:
    461
    I've had success with this kind of code on a project. I think it does exactly what you described.

    Code (CSharp):
    1. public static TerrainLayer FindTerrainLayerBelow(Vector3 position, float distance, int layerMask)
    2. {
    3.     RaycastHit raycastHit;
    4.     if (Physics.Raycast(position, Vector3.down, out raycastHit, distance, layerMask))
    5.     {
    6.         if (raycastHit.collider is TerrainCollider)
    7.         {
    8.             Terrain terrain = raycastHit.collider.transform.gameObject.GetComponent<Terrain>();
    9.             if (terrain != null)
    10.             {
    11.                 return GetStrongestTerrainLayer(position, terrain);
    12.             }
    13.         }
    14.     }
    15.  
    16.     return null;
    17. }
    18.  
    19. private static TerrainLayer GetStrongestTerrainLayer(Vector3 position, Terrain terrain)
    20. {
    21.     Vector3 terrainPosition = terrain.transform.position;
    22.     TerrainData terrainData = terrain.terrainData;
    23.  
    24.     int x = Mathf.RoundToInt((position.x - terrainPosition.x) / terrainData.size.x * terrainData.alphamapWidth);
    25.     int z = Mathf.RoundToInt((position.z - terrainPosition.z) / terrainData.size.z * terrainData.alphamapWidth);
    26.     float[,,] splatMapData = terrainData.GetAlphamaps(x, z, 1, 1);
    27.  
    28.     float strongest = 0f;
    29.     int maxIndex = 0;
    30.  
    31.     for (int i = 0; i < splatMapData.GetUpperBound(2) + 1; ++i)
    32.     {
    33.         if (splatMapData[0, 0, i] > strongest)
    34.         {
    35.             maxIndex = i;
    36.             strongest = splatMapData[0, 0, i];
    37.         }
    38.     }
    39.  
    40.     return terrain.terrainData.terrainLayers[maxIndex];
    41. }
    42.  
     
  3. softdist0rtion

    softdist0rtion

    Joined:
    Nov 10, 2023
    Posts:
    2
    Hi, thank you for the response. Unfortunately I'm fairly certain this code would only work with mulitple terrain textures. The terrain on my project is a custom shader, and is all one material. Regardless, this code could still be a very useful starting point, so many thanks!
     
    SeventhString likes this.