'Unity: Runtime-Terrain-Editor How to raise a circle

I'm trying to create a terrain editor, that works on runtime. At this point I can raise a square but have problems to raise a circle-shape. I saw this post and thoughts thats the solution for my problem, so I transfered it to my code. It really raise a circle somewhere (where I dont click) but its not efficient, because its updating the whole terrain.

The whole function:

    public void RaiseTerrain(Terrain terrain, Vector3 location, float effectIncrement)
{
    int offset = areaOfEffectSize / 2;

    Vector3 tempCoord = (location - terrain.GetPosition());
    Vector3 coord;

    coord = new Vector3(
        (tempCoord.x / GetTerrainSize().x),
        (tempCoord.y / GetTerrainSize().y),
        (tempCoord.z / GetTerrainSize().z)
        );

    Vector3 locationInTerrain = new Vector3(coord.x * terrainHeightMapWidth, 0, coord.z * terrainHeightMapHeight);

    int terX = (int)locationInTerrain.x - offset;
    int terZ = (int)locationInTerrain.z - offset;
    int terXInv = (int)locationInTerrain.x + offset;
    int terZInv = (int)locationInTerrain.z + offset;

    //This raises a square
    //float[,] heights = targetTerrainData.GetHeights(terX, terZ, areaOfEffectSize, areaOfEffectSize);

    //for (int xx = 0; xx < areaOfEffectSize; xx++)
    //{
    //    for (int yy = 0; yy < areaOfEffectSize; yy++)
    //    {
    //        heights[xx, yy] += (effectIncrement * Time.smoothDeltaTime);
    //    }
    //}
    //targetTerrainData.SetHeights(terX, terZ, heights);

    //This raises a circle
    float[,] heights = targetTerrainData.GetHeights(0, 0, terrainHeightMapWidth, terrainHeightMapHeight);

    for (int xx = terX; xx < terXInv; xx++)
    {
        for (int yy = terZ; yy < terZInv; yy++)
        {
            float currentRadiusSqr = (new Vector2(locationInTerrain.x, locationInTerrain.z) - new Vector2(xx, yy)).sqrMagnitude;
            if(currentRadiusSqr < offset*offset)
            {
                heights[xx, yy] += (effectIncrement * Time.smoothDeltaTime);
            }                
        }
    }
    targetTerrainData.SetHeights(0, 0, heights);
}

All following lines are just excerpts from above.

I guess my problem is this line:

float[,] heights = targetTerrainData.GetHeights(0, 0, terrainHeightMapWidth, terrainHeightMapHeight);

Because raising a square works fine. I just update a specific area, so its updating the terrain without dropping framerate:

float[,] heights = targetTerrainData.GetHeights(terX, terZ, areaOfEffectSize, areaOfEffectSize);
[...]
targetTerrainData.SetHeights(terX, terZ, heights);

So my question is, how can I raise a circle and update the changes like I did with raising a square? Update only the changed heights?

I tried to use this lines from the square:

float[,] heights = targetTerrainData.GetHeights(terX, terZ, areaOfEffectSize, areaOfEffectSize);
[...]
targetTerrainData.SetHeights(terX, terZ, heights);

in comination with:

        for (int xx = terX; xx < terXInv; xx++)
    {
        for (int yy = terZ; yy < terZInv; yy++)
        {
            float currentRadiusSqr = (new Vector2(locationInTerrain.x, locationInTerrain.z) - new Vector2(xx, yy)).sqrMagnitude;
            if(currentRadiusSqr < offset*offset)
            {
                heights[xx, yy] += (effectIncrement * Time.smoothDeltaTime);
            }                
        }
    }

but it didnt work. Im getting an error:

IndexOutOfRangeException: Index was outside the bounds of the array.


Solution 1:[1]

instead of heights[xx, yy] += (effectIncrement * Time.smoothDeltaTime); try heights[yy, xx] += (effectIncrement * Time.smoothDeltaTime); this seems to work for me

int offset = radious / 2;

int mouseX = (int)((point.x / terrainData.size.x) * heightmapWidth);
int mouseZ = (int)((point.z / terrainData.size.z) * heightmapHeight);

int terX = mouseX - offset;
int terZ = mouseZ - offset;
int terXInv = mouseX + offset;
int terZInv = mouseZ + offset;


    
float[,] heights = terrainData.GetHeights(0, 0, heightmapWidth, heightmapHeight);
    
for (int xx = terX; xx < terXInv; xx++)
{
    for (int yy = terZ; yy < terZInv; yy++)
    {
        float currentRadiusSqr = (new Vector2(mouseX, mouseZ) - new Vector2(xx, yy)).sqrMagnitude;
            
        if (currentRadiusSqr < offset * offset)
        {
            heights[yy, xx] += (strength * Time.smoothDeltaTime);
        }
    }
}
terrainData.SetHeights(0, 0, heights);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Damon Nomad