OK, so I took your code that process a grid, using the distance from the centre to calculate the hill height.
Now, if you use a linear function you’ll get a linear/sharp hill.
So, my version uses a bezier function which creates a nice sloping hill.
[ExecuteInEditMode]
public class HillGenerator : MonoBehaviour
{
public int x;
public int y;
public int radius;
public float height;
}
[CustomEditor (typeof(HillGenerator))]
public class HillGeneratorEditor : Editor
{
public static Vector2 BezierCurve(float t, Vector2 pOne, Vector2 pTwo, Vector2 pThree, Vector2 pFour)
{
return Mathf.Pow (1 - t, 3) * pOne + 3 * Mathf.Pow (1 - t, 2) * t * pTwo + 3 * (1 - t) * t * t * pThree + Mathf.Pow (t, 3) * pFour;
}
public override void OnInspectorGUI()
{
DrawDefaultInspector ();
var script = this.target as HillGenerator;
if (GUILayout.Button ("Generate"))
{
this.CreateHill (script.x, script.y, script.height, script.radius);
}
}
public void CreateHill(int x, int y, float height, int radius)
{
var diameter = radius * 2;
var heightsCenteX = radius;
var heightsCenteY = radius;
var baseX = x - heightsCenteX;
var baseY = y - heightsCenteY;
var script = this.target as HillGenerator;
var terrianData = script.GetComponent<Terrain> ().terrainData;
var heights = terrianData.GetHeights (baseX, baseY, diameter, diameter);
var controlPoint1 = new Vector2 (0.52f, 0.06f);
var controlPoint2 = new Vector2 (0.42f, 0.95f);
for (int a = 0; a < diameter; a++)
{
for (int b = 0; b < diameter; b++)
{
var distanceFromCenter = Mathf.Sqrt (Mathf.Pow ((heightsCenteY - b), 2) + Mathf.Pow ((heightsCenteX - a), 2));
var time = Math.Max (1 - (distanceFromCenter / radius), 0);
var bezierPoint = BezierCurve (time, new Vector2 (0, 0), controlPoint1, controlPoint2, new Vector2 (1, 1));
var pointHeight = bezierPoint.y * height;
if (pointHeight < 0)
pointHeight = 0;
heights [a, b] = pointHeight;
}
}
terrianData.SetHeights (baseX, baseY, heights);
}
}
example: CreateHill(250, 250, 0.3, 100)
To visualise the curve you can use this site:
controlPoint1 = site.point1 & 2
controlPoint2 = site.point3 & 4
Attach the script to a Terrain
, set up the properties and hit Generate.