Mowing The Lawn (fps expensive)

I have a script that works perfectly for cutting grass but its very! expensive on the frames.
example: 150 fps down to 10 fps.
can anyone help me with a solution or point me in the right direction.

 public float Radius;
    public LayerMask layerMask;


    protected int[,] BackupMap;
    Terrain te;

    // Use this for initialization
    void Start()
    {
        //te.GetComponent<Terrain>();
       te = GameObject.FindObjectOfType<Terrain>();
        CreateBackup(te);
    }

    void FixedUpdate()
    {

        //NOTE FOR TESTING

        if (Input.GetMouseButton(0))
        {
            RaycastHit hit;
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out hit, 99f, layerMask))
            {
                Debug.Log(hit.point);
                CutGrass(null, hit.point, Radius);
            }
        }

        if (Input.GetMouseButton(1))
        {
            RaycastHit hit;
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out hit, 99999999f, layerMask))
            {
                Debug.Log(hit.point);
                PlantGrass(null, hit.point, Radius);
            }
        }

    }

    ///
    /// Cuts the grass. BE CAREFULL: Grass may not respawn after game reset!!!!!!
    ///
    /// The effected Terrain, if only one Terrain pass null
    /// The world position you want to cut the grass
    /// the radius of the square
    public void CutGrass(Terrain t, Vector3 position, float radius)
    {
        if (t == null)
           t = GameObject.FindObjectOfType<Terrain>();

        int TerrainDetailMapSize = t.terrainData.detailResolution;
        if (t.terrainData.size.x != t.terrainData.size.z)
        {
            Debug.Log("X and Y Size of terrain have to be the same (RemoveGrass.CS Line 43)");
            return;
        }

        float PrPxSize = TerrainDetailMapSize / t.terrainData.size.x;

        Vector3 TexturePoint3D = position - t.transform.position;
        TexturePoint3D = TexturePoint3D * PrPxSize;

        Debug.Log(TexturePoint3D);

        float[] xymaxmin = new float[4];
        xymaxmin[0] = TexturePoint3D.z + radius;
        xymaxmin[1] = TexturePoint3D.z - radius;
        xymaxmin[2] = TexturePoint3D.x + radius;
        xymaxmin[3] = TexturePoint3D.x - radius;


        int[,] map = t.terrainData.GetDetailLayer(0, 0, t.terrainData.detailWidth, t.terrainData.detailHeight, 0);

        for (int y = 0; y < t.terrainData.detailHeight; y++)
        {
            for (int x = 0; x < t.terrainData.detailWidth; x++)
            {

                if (xymaxmin[0] > x && xymaxmin[1] < x && xymaxmin[2] > y && xymaxmin[3] < y)
                    map[x, y] = 0;
            }
        }
        t.terrainData.SetDetailLayer(0, 0, 0, map);
    }

    public void PlantGrass(Terrain t, Vector3 position, float radius)
    {
        if (t == null)
          t = GameObject.FindObjectOfType<Terrain>();

        int TerrainDetailMapSize = t.terrainData.detailResolution;
        if (t.terrainData.size.x != t.terrainData.size.z)
        {
            Debug.Log("X and Y Size of terrain have to be the same (RemoveGrass.CS Line 43)");
            return;
        }

        float PrPxSize = TerrainDetailMapSize / t.terrainData.size.x;

        Vector3 TexturePoint3D = position - t.transform.position;
        TexturePoint3D = TexturePoint3D * PrPxSize;

        Debug.Log(TexturePoint3D);

        float[] xymaxmin = new float[4];
        xymaxmin[0] = TexturePoint3D.z + radius;
        xymaxmin[1] = TexturePoint3D.z - radius;
        xymaxmin[2] = TexturePoint3D.x + radius;
        xymaxmin[3] = TexturePoint3D.x - radius;


        int[,] map = t.terrainData.GetDetailLayer(0, 0, t.terrainData.detailWidth, t.terrainData.detailHeight, 0);

        for (int y = 0; y < t.terrainData.detailHeight; y++)
        {
            if (xymaxmin[2] > y && xymaxmin[3] < y)
            {
                for (int x = 0; x < t.terrainData.detailWidth; x++)
                {

                    if (xymaxmin[0] > x && xymaxmin[1] < x)
                        map[x, y] = 1;
                }
            }
        }
        t.terrainData.SetDetailLayer(0, 0, 0, map);
    }

    void CreateBackup(Terrain t)
    {
        Debug.Log("DetailBackup Done");
        BackupMap = t.terrainData.GetDetailLayer(0, 0, t.terrainData.detailWidth, t.terrainData.detailHeight, 0);
    }

    void OnDestroy()
    {
        Debug.Log("I work !!! ");
        te.terrainData.SetDetailLayer(0, 0, 0, BackupMap);
    }
}

ouch…
Dealing with the detail layer of a terrain is hard enough, but doing it every fixed update?

First, try moving the method to Update.

Also, combine the plant and cut methods. Getting and setting that detail layer is rough on cpu usage, cut it down as much as possible.

Don’t forget how horrifically expensive Debug.Log is (full stack trace each time).

Personally I’d just read grass height from a render texture inside the grass shader, then it’s trivial and costs practically nothing to change (or mow) since you keep it all on the gpu.