Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Probuilder flatten terrain over time

Discussion in 'World Building' started by stychu, Feb 10, 2021.

  1. stychu

    stychu

    Joined:
    May 9, 2016
    Posts:
    62
    Hello there,

    I'm trying to make some kind of animation for flattening the terrain over some x period of time.
    But unfortunately, my terrain flattens almost at a constant speed regardless of the time it should take.

    So pretty much no matter what duration I set it flattens really quick and I have to wait for the Debug.log to fire rest of the time. Whereas I would like it to flatten at the speed of duration so it really takes some x seconds before it's flattened

    My code:

    Code (CSharp):
    1. IEnumerator FlattenTerrain(float duration) {
    2.     float time = 0;
    3.     Vertex[] vertices = m_Mesh.GetVertices();
    4.  
    5.    // lerp vertices to 0 over time
    6.     while (time < duration) {
    7.       foreach (Vertex vertex in vertices) {
    8.         if (vertex.position.y <= Mathf.Epsilon)
    9.           continue;
    10.  
    11.         Vector3 newPosition = vertex.position;
    12.         newPosition.y = Mathf.Lerp(vertex.position.y, 0, time / duration);
    13.  
    14.         vertex.position = newPosition;
    15.       }
    16.  
    17.       time += Time.deltaTime;
    18.  
    19.       m_Mesh.SetVertices(vertices);
    20.       m_Mesh.ToMesh();
    21.       m_Mesh.Refresh();
    22.  
    23.       yield return null;
    24.     }
    25.  
    26.   // set vertices exactly to 0 because of overshoot
    27.     Vertex[] flattenedVertices = m_Mesh.GetVertices()
    28.      .Select(
    29.         vertex => {
    30.           Vector3 pos = vertex.position;
    31.           vertex.position = new Vector3(pos.x, 0, pos.z);
    32.  
    33.           return vertex;
    34.         }
    35.       )
    36.      .ToArray();
    37.  
    38.     m_Mesh.SetVertices(flattenedVertices);
    39.     m_Mesh.ToMesh();
    40.     m_Mesh.Refresh();
    41.  
    42.     MeshUtility.CollapseSharedVertices(m_Mesh.GetComponent<MeshFilter>().sharedMesh);
    43.     Debug.Log("VAR");
    44.   }

    Attached gif -> 2 seconds duration and terrain flattens crazy fast instead over time
    UdYa7LxzPX.gif
     
  2. stychu

    stychu

    Joined:
    May 9, 2016
    Posts:
    62
    I got something better but still I don't know how to incorporate Time into the flattening. Now I can flatten at some speed but can't figure out how to add time variable here so It would really take some X time to flatten..


    Code (CSharp):
    1.   private IEnumerator FlattenTerrain(float flattenSpeed) {
    2.     float time = 0;
    3.     float verticesLeft = float.MaxValue;
    4.  
    5.     Vertex[] vertices = m_Mesh.GetVertices();
    6.  
    7.     while (verticesLeft >= Mathf.Epsilon) {
    8.       foreach (Vertex vertex in vertices) {
    9.         if (vertex.position.y <= Mathf.Epsilon)
    10.           continue;
    11.  
    12.         Vector3 startPos = vertex.position;
    13.         Vector3 endPos = new Vector3(startPos.x, 0, startPos.z);
    14.  
    15.         float distCovered = time * flattenSpeed;
    16.         float fractionOfJourney = distCovered / Vector3.Distance(startPos, endPos);
    17.  
    18.         vertex.position = Vector3.Lerp(startPos, endPos, fractionOfJourney);
    19.       }
    20.  
    21.       time += Time.deltaTime;
    22.  
    23.       m_Mesh.SetVertices(vertices);
    24.       m_Mesh.ToMesh();
    25.       m_Mesh.Refresh();
    26.  
    27.       yield return null;
    28.  
    29.       verticesLeft = vertices.Sum(vertex => vertex.position.y);
    30.     }
    31.  
    32.     Vertex[] flattenedVertices = m_Mesh.GetVertices()
    33.      .Select(
    34.         vertex => {
    35.           Vector3 pos = vertex.position;
    36.           vertex.position = new Vector3(pos.x, 0, pos.z);
    37.  
    38.           return vertex;
    39.         }
    40.       )
    41.      .ToArray();
    42.  
    43.     m_Mesh.SetVertices(flattenedVertices);
    44.     m_Mesh.ToMesh();
    45.     m_Mesh.Refresh();
    46.  
    47.     MeshUtility.CollapseSharedVertices(m_Mesh.GetComponent<MeshFilter>().sharedMesh);
    48.  
    49.     StopCoroutine(flattenRoutine);
    50.   }
    51. }