generate procedural floating island

i want make simple lowpoly procedural generation floating island in unity,like this :

so I decided to make a simple sphere then I flattened the top and randomly generated the bottom noise but several times I tried I did not get the results I wanted, like a right curve and no taper

163642-screen-shot-2020-07-19-at-092325.png

so how can I get results the right mesh? Is there something wrong with my code? or is there another algorithm that I can use?

the code I’ve used so far…

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SphereGenerator : MonoBehaviour
{   

    public float minRadius = 1f;
    Vector3[] vertices;
    Vector3[] normales;
    Vector2[] uvs;
    int[] triangles;
    MeshFilter filter;


    // Start is called before the first frame update
    void Start()
    {
        
       StartCoroutine(createMesh());
    }

    // Update is called once per frame
    void Update()
    {
        updateMesh();
    }

    IEnumerator createMesh(){
        float radius = minRadius;
        // Longitude |||
        int nbLong = 24;
        // Latitude ---
        int nbLat = 16;
        
        #region Vertices
        vertices = new Vector3[(nbLong+1) * nbLat + 2];
        float _pi = Mathf.PI;
        float _2pi = _pi * 2f;
        
        vertices[0] = Vector3.zero;

        float y = 0f;
        for( int lat = 0; lat < nbLat; lat++ )
        {
            float a1 = _pi * (float)(lat+1) / (nbLat+1);
            float sin1 = Mathf.Sin(a1);
            float cos1 = Mathf.Cos(a1);
        
            for( int lon = 0; lon <= nbLong; lon++ )
            {
                float a2 = _2pi * (float)(lon == nbLong ? 0 : lon) / nbLong;
                float sin2 = Mathf.Sin(a2);
                float cos2 = Mathf.Cos(a2);
                y = cos1 - Mathf.PerlinNoise(Time.time*1f,0f) * 2f;
                float x = Time.time*(sin1 * cos2) * Random.Range(0f,1f);
                float z = Time.time*(sin1 * sin2) * Random.Range(0f,1f);

                //check top half
                if(lat <= nbLat/2){
                    // float height = Random.Range(0f,0.1f);
                    // Debug.Log(height);
                    // y = height;
                    y = 0f;
                } else {
                    z = (sin1 * sin2) * Random.Range(0f,1f);
                }

                float newRad = radius;
                newRad = radius + Mathf.PerlinNoise(x,z) * 2f;
                vertices[ lon + lat * (nbLong + 1) + 1] = new Vector3( sin1 * cos2, y, sin1 * sin2 ) * newRad;
            }
        }
         vertices[vertices.Length-1] = Vector3.up * (-radius + y - Random.Range(0f,1f));
        #endregion
        
        #region Normales		
        normales = new Vector3[vertices.Length];
        for( int n = 0; n < vertices.Length; n++ )
            normales[n] = vertices[n].normalized;
        #endregion
        
        #region UVs
        uvs = new Vector2[vertices.Length];
        uvs[0] = Vector2.up;
        uvs[uvs.Length-1] = Vector2.zero;
        for( int lat = 0; lat < nbLat; lat++ )
            for( int lon = 0; lon <= nbLong; lon++ )
                uvs[lon + lat * (nbLong + 1) + 1] = new Vector2( (float)lon / nbLong, 1f - (float)(lat+1) / (nbLat+1) );
        #endregion
        
        #region Triangles
        int nbFaces = vertices.Length;
        int nbTriangles = nbFaces * 2;
        int nbIndexes = nbTriangles * 3;
        triangles = new int[ nbIndexes ];
        
        //Top Cap
        int i = 0;
        for( int lon = 0; lon < nbLong; lon++ )
        {
            triangles[i++] = lon+2;
            triangles[i++] = lon+1;
            triangles[i++] = 0;
        }
        
        //Middle
        for( int lat = 0; lat < nbLat - 1; lat++ )
        {
            for( int lon = 0; lon < nbLong; lon++ )
            {
                int current = lon + lat * (nbLong + 1) + 1;
                int next = current + nbLong + 1;
        
                triangles[i++] = current;
                triangles[i++] = current + 1;
                triangles[i++] = next + 1;
        
                triangles[i++] = current;
                triangles[i++] = next + 1;
                triangles[i++] = next;

                yield return new WaitForSeconds(.05f);
            }
        }
        
        //Bottom Cap
        for( int lon = 0; lon < nbLong; lon++ )
        {
            triangles[i++] = vertices.Length - 1;
            triangles[i++] = vertices.Length - (lon+2) - 1;
            triangles[i++] = vertices.Length - (lon+1) - 1;
        }
        #endregion
        
    }

    void updateMesh(){
        filter = gameObject.GetComponent< MeshFilter >();
        Mesh mesh = new Mesh();
        mesh.Clear();
        mesh.vertices = vertices;
        mesh.normals = normales;
        mesh.uv = uvs;
        mesh.triangles = triangles;
        mesh.RecalculateNormals();
        mesh.RecalculateBounds();
        mesh.Optimize();
        filter.mesh = mesh;
    }
}

I have taken references from:

Have you figured it out?,Did you figure it out?

This may not be what you’re looking for, but couldn’t you just model different islands and then choose a random one from the list? If you had about 20 different models, no one would ever be able to tell the difference anyway, but you could get exactly the kind of island you wanted.