Terrain heights changed in the network(runtime)

Hi developers.
I have a few problem with Server and Client

Players are digging terrain
Firts,[ClientRpc] is working.
Image

if I didn’t use [Command],Client is digging but not showing on server,Thats ok.

But if I use [Command],Client is digging and showing on server but client not see himself hole.
Image


And so strange,example,client digging 2 meters but showing 1 meter on server. :smile:
And of course not sees client from client.
I Confused :hushed::face_with_spiral_eyes:

Code Here

using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public class Kazma :NetworkBehaviour
{

    public ParticleSystem partikul;

    public bool MouseActive = false;
    public Terrain myTerrain;
    public int SmoothArea;
    private int xResolution;
    private int zResolution;
    public float[,] heights;
    private float[,] heightMapBackup;
    protected const float DEPTH_METER_CONVERT=0.05f;
    protected const float TEXTURE_SIZE_MULTIPLIER = 1.25f;
    public int DeformationTextureNum = 1;
    protected int alphaMapWidth;
    protected int alphaMapHeight;
    protected int numOfAlphaLayers;
    private float[, ,] alphaMapBackup;

    public Transform camTransform;
    public float range;

    float hitWaitTime;
    bool startTime;

    void Start()
    {
            Cursor.visible = false;
            xResolution = myTerrain.terrainData.heightmapWidth;
            zResolution = myTerrain.terrainData.heightmapHeight;
            alphaMapWidth = myTerrain.terrainData.alphamapWidth;
            alphaMapHeight = myTerrain.terrainData.alphamapHeight;
            numOfAlphaLayers = myTerrain.terrainData.alphamapLayers;

            if (Debug.isDebugBuild)
            {
                heights = myTerrain.terrainData.GetHeights (0, 0, xResolution, zResolution);    
                heightMapBackup = myTerrain.terrainData.GetHeights(0, 0, xResolution, zResolution);
                alphaMapBackup = myTerrain.terrainData.GetAlphamaps(0, 0, alphaMapWidth, alphaMapHeight); 
            }
    }


    void Update()
    {
        if (MouseActive == true) 
        {
            if (Input.GetMouseButtonDown (0))
            {
                startTime = true;
            }

            if (startTime == true) 
            {
                DigWaitTimer ();
            }
        }
    }

    void DigWaitTimer()
    {
        hitWaitTime += Time.deltaTime;
        if (hitWaitTime > 1) 
        {
            hitWaitTime = 0;
            Dig ();
            startTime = false;
        }
    }


    public void Dig()
    {
        if (!isServer) 
        {
            RaycastHit hit;
            Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
            if (Physics.Raycast (ray, out hit, range)) 
            {

                partikul.Emit (3);
                // area middle point x and z, area width, area height, smoothing distance, area height adjust
                CmdraiselowerTerrainArea (hit.point, 2, 2, SmoothArea, -0.0005f);
                // area middle point x and z, area size, texture ID from terrain textures
                CmdTextureDeformation (hit.point, 2, DeformationTextureNum);
            }
        }        

        if (isServer) 
        {
                RaycastHit hit;
                Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
                if (Physics.Raycast (ray, out hit, range)) 
                {

                    partikul.Emit (3);
                    // area middle point x and z, area width, area height, smoothing distance, area height adjust
                    RpcraiselowerTerrainArea (hit.point, 2, 2, SmoothArea, -0.0005f);
                    // area middle point x and z, area size, texture ID from terrain textures
                    RpcTextureDeformation (hit.point, 2, DeformationTextureNum);
                }
        }
    }


    [Command]
    public void CmdraiselowerTerrainArea(Vector3 point, int lenx, int lenz, int smooth,float incdec)
    {
            int areax;
            int areaz;
            smooth += 1;
            float smoothing;
            int terX =(int)((point.x / myTerrain.terrainData.size.x) * xResolution);
            int terZ =(int)((point.z / myTerrain.terrainData.size.z) * zResolution);
            lenx += smooth;
            lenz += smooth;
            terX -= (lenx / 2);
            terZ -= (lenz / 2);
            if (terX < 0) terX = 0;
            if (terX > xResolution)    terX = xResolution;
            if (terZ < 0) terZ = 0;
            if (terZ > zResolution)    terZ = zResolution;
            float[,] heights = myTerrain.terrainData.GetHeights(terX, terZ, lenx, lenz);
            float y = heights[lenx/2,lenz/2];
            y += incdec;
            for (smoothing=1; smoothing < smooth+1; smoothing++) 
            {
                float multiplier = smoothing / smooth;
                for (areax = (int)(smoothing/2); areax < lenx-(smoothing/2); areax++) 
                {
                    for (areaz = (int)(smoothing/2); areaz < lenz-(smoothing/2); areaz++) 
                    {
                        if ((areax > -1) && (areaz > -1) && (areax < xResolution) && (areaz < zResolution)) 
                        {
                            heights [areax, areaz] = Mathf.Clamp((float)y*multiplier,0,1);
                        }
                    }
                }
            }
            myTerrain.terrainData.SetHeights (terX, terZ, heights);
    }


    [Command]
    public void CmdTextureDeformation(Vector3 pos, float craterSizeInMeters,int textureIDnum)
    {
       
        Vector3 alphaMapTerrainPos = GetRelativeTerrainPositionFromPos(pos, myTerrain, alphaMapWidth, alphaMapHeight);
        int alphaMapCraterWidth = (int)(craterSizeInMeters * (alphaMapWidth / myTerrain.terrainData.size.x));
        int alphaMapCraterLength = (int)(craterSizeInMeters * (alphaMapHeight / myTerrain.terrainData.size.z));
        int alphaMapStartPosX = (int)(alphaMapTerrainPos.x - (alphaMapCraterWidth / 2));
        int alphaMapStartPosZ = (int)(alphaMapTerrainPos.z - (alphaMapCraterLength/2));
        float[, ,] alphas = myTerrain.terrainData.GetAlphamaps(alphaMapStartPosX, alphaMapStartPosZ, alphaMapCraterWidth, alphaMapCraterLength);
        float circlePosX;
        float circlePosY;
        float distanceFromCenter;
        for (int i = 0; i < alphaMapCraterLength; i++) //width
        {
            for (int j = 0; j < alphaMapCraterWidth; j++) //height
            {
                circlePosX = (j - (alphaMapCraterWidth / 2)) / (alphaMapWidth / myTerrain.terrainData.size.x);
                circlePosY = (i - (alphaMapCraterLength / 2)) / (alphaMapHeight / myTerrain.terrainData.size.z);
                distanceFromCenter = Mathf.Abs(Mathf.Sqrt(circlePosX * circlePosX + circlePosY * circlePosY));
                if (distanceFromCenter < (craterSizeInMeters / 2.0f))
                {
                    for (int layerCount = 0; layerCount < numOfAlphaLayers; layerCount++)
                    {
                        //could add blending here in the future
                        if (layerCount == textureIDnum)
                        {
                            alphas[i, j, layerCount] = 1;
                        }
                        else
                        {
                            alphas[i, j, layerCount] = 0;
                        }
                    }
                }
            }
        } 
        myTerrain.terrainData.SetAlphamaps(alphaMapStartPosX, alphaMapStartPosZ, alphas);
    }


[ClientRpc]
    public void RpcraiselowerTerrainArea(Vector3 point, int lenx, int lenz, int smooth,float incdec)
    {

        int areax;
        int areaz;
        smooth += 1;
        float smoothing;
        int terX =(int)((point.x / myTerrain.terrainData.size.x) * xResolution);
        int terZ =(int)((point.z / myTerrain.terrainData.size.z) * zResolution);
        lenx += smooth;
        lenz += smooth;
        terX -= (lenx / 2);
        terZ -= (lenz / 2);
        if (terX < 0) terX = 0;
        if (terX > xResolution)    terX = xResolution;
        if (terZ < 0) terZ = 0;
        if (terZ > zResolution)    terZ = zResolution;
        float[,] heights = myTerrain.terrainData.GetHeights(terX, terZ, lenx, lenz);
        float y = heights[lenx/2,lenz/2];
        y += incdec;
        for (smoothing=1; smoothing < smooth+1; smoothing++) 
        {
            float multiplier = smoothing / smooth;
            for (areax = (int)(smoothing/2); areax < lenx-(smoothing/2); areax++) 
            {
                for (areaz = (int)(smoothing/2); areaz < lenz-(smoothing/2); areaz++) 
                {
                    if ((areax > -1) && (areaz > -1) && (areax < xResolution) && (areaz < zResolution)) 
                    {
                        heights [areax, areaz] = Mathf.Clamp((float)y*multiplier,0,1);
                    }
                }
            }
        }
        myTerrain.terrainData.SetHeights (terX, terZ, heights);
    }


    [ClientRpc]
    public void RpcTextureDeformation(Vector3 pos, float craterSizeInMeters,int textureIDnum)
    {
        Vector3 alphaMapTerrainPos = GetRelativeTerrainPositionFromPos(pos, myTerrain, alphaMapWidth, alphaMapHeight);
        int alphaMapCraterWidth = (int)(craterSizeInMeters * (alphaMapWidth / myTerrain.terrainData.size.x));
        int alphaMapCraterLength = (int)(craterSizeInMeters * (alphaMapHeight / myTerrain.terrainData.size.z));
        int alphaMapStartPosX = (int)(alphaMapTerrainPos.x - (alphaMapCraterWidth / 2));
        int alphaMapStartPosZ = (int)(alphaMapTerrainPos.z - (alphaMapCraterLength/2));
        float[, ,] alphas = myTerrain.terrainData.GetAlphamaps(alphaMapStartPosX, alphaMapStartPosZ, alphaMapCraterWidth, alphaMapCraterLength);
        float circlePosX;
        float circlePosY;
        float distanceFromCenter;
        for (int i = 0; i < alphaMapCraterLength; i++) //width
        {
            for (int j = 0; j < alphaMapCraterWidth; j++) //height
            {
                circlePosX = (j - (alphaMapCraterWidth / 2)) / (alphaMapWidth / myTerrain.terrainData.size.x);
                circlePosY = (i - (alphaMapCraterLength / 2)) / (alphaMapHeight / myTerrain.terrainData.size.z);
                distanceFromCenter = Mathf.Abs(Mathf.Sqrt(circlePosX * circlePosX + circlePosY * circlePosY));
                if (distanceFromCenter < (craterSizeInMeters / 2.0f))
                {
                    for (int layerCount = 0; layerCount < numOfAlphaLayers; layerCount++)
                    {
                        //could add blending here in the future
                        if (layerCount == textureIDnum)
                        {
                            alphas[i, j, layerCount] = 1;
                        }
                        else
                        {
                            alphas[i, j, layerCount] = 0;
                        }
                    }
                }
            }
        } 
        myTerrain.terrainData.SetAlphamaps(alphaMapStartPosX, alphaMapStartPosZ, alphas);
    }


    protected Vector3 GetNormalizedPositionRelativeToTerrain(Vector3 pos, Terrain terrain)
    {
        Vector3 tempCoord = (pos - terrain.gameObject.transform.position);
        Vector3 coord;
        coord.x = tempCoord.x / myTerrain.terrainData.size.x;
        coord.y = tempCoord.y / myTerrain.terrainData.size.y;
        coord.z = tempCoord.z / myTerrain.terrainData.size.z;
        return coord;
    }

    protected Vector3 GetRelativeTerrainPositionFromPos(Vector3 pos,Terrain terrain, int mapWidth, int mapHeight)
    {
        Vector3 coord = GetNormalizedPositionRelativeToTerrain(pos, terrain);
        return new Vector3((coord.x * mapWidth), 0, (coord.z * mapHeight));
    }    
}

You should send CmdDigAtPosition(Vector3 placeWherePlayerClicked), then modify the terrain, then synchronize the new terrain to all players (in range). If you send an RPC that modifies the terrain on the client then new clients that join later on won’t see previous terrain modifications.

Thanks for answer
I Understand rationale but
How can I make that,could you give an example ?
I am new to this topic