Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Terrain heights changed in the network(runtime)

Discussion in 'Multiplayer' started by nsns, Aug 14, 2017.

  1. nsns

    nsns

    Joined:
    Oct 28, 2013
    Posts:
    11
    Hi developers.
    I have a few problem with Server and Client

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

    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
    1.png
    And so strange,example,client digging 2 meters but showing 1 meter on server. :D
    And of course not sees client from client.
    I Confused :eek::confused:


    Code Here
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.Networking;
    4. using UnityEngine.UI;
    5.  
    6. public class Kazma :NetworkBehaviour
    7. {
    8.  
    9.     public ParticleSystem partikul;
    10.  
    11.     public bool MouseActive = false;
    12.     public Terrain myTerrain;
    13.     public int SmoothArea;
    14.     private int xResolution;
    15.     private int zResolution;
    16.     public float[,] heights;
    17.     private float[,] heightMapBackup;
    18.     protected const float DEPTH_METER_CONVERT=0.05f;
    19.     protected const float TEXTURE_SIZE_MULTIPLIER = 1.25f;
    20.     public int DeformationTextureNum = 1;
    21.     protected int alphaMapWidth;
    22.     protected int alphaMapHeight;
    23.     protected int numOfAlphaLayers;
    24.     private float[, ,] alphaMapBackup;
    25.  
    26.     public Transform camTransform;
    27.     public float range;
    28.  
    29.     float hitWaitTime;
    30.     bool startTime;
    31.  
    32.     void Start()
    33.     {
    34.             Cursor.visible = false;
    35.             xResolution = myTerrain.terrainData.heightmapWidth;
    36.             zResolution = myTerrain.terrainData.heightmapHeight;
    37.             alphaMapWidth = myTerrain.terrainData.alphamapWidth;
    38.             alphaMapHeight = myTerrain.terrainData.alphamapHeight;
    39.             numOfAlphaLayers = myTerrain.terrainData.alphamapLayers;
    40.  
    41.             if (Debug.isDebugBuild)
    42.             {
    43.                 heights = myTerrain.terrainData.GetHeights (0, 0, xResolution, zResolution);    
    44.                 heightMapBackup = myTerrain.terrainData.GetHeights(0, 0, xResolution, zResolution);
    45.                 alphaMapBackup = myTerrain.terrainData.GetAlphamaps(0, 0, alphaMapWidth, alphaMapHeight);
    46.             }
    47.     }
    48.  
    49.  
    50.     void Update()
    51.     {
    52.         if (MouseActive == true)
    53.         {
    54.             if (Input.GetMouseButtonDown (0))
    55.             {
    56.                 startTime = true;
    57.             }
    58.  
    59.             if (startTime == true)
    60.             {
    61.                 DigWaitTimer ();
    62.             }
    63.         }
    64.     }
    65.  
    66.     void DigWaitTimer()
    67.     {
    68.         hitWaitTime += Time.deltaTime;
    69.         if (hitWaitTime > 1)
    70.         {
    71.             hitWaitTime = 0;
    72.             Dig ();
    73.             startTime = false;
    74.         }
    75.     }
    76.  
    77.  
    78.     public void Dig()
    79.     {
    80.         if (!isServer)
    81.         {
    82.             RaycastHit hit;
    83.             Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
    84.             if (Physics.Raycast (ray, out hit, range))
    85.             {
    86.  
    87.                 partikul.Emit (3);
    88.                 // area middle point x and z, area width, area height, smoothing distance, area height adjust
    89.                 CmdraiselowerTerrainArea (hit.point, 2, 2, SmoothArea, -0.0005f);
    90.                 // area middle point x and z, area size, texture ID from terrain textures
    91.                 CmdTextureDeformation (hit.point, 2, DeformationTextureNum);
    92.             }
    93.         }        
    94.  
    95.         if (isServer)
    96.         {
    97.                 RaycastHit hit;
    98.                 Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
    99.                 if (Physics.Raycast (ray, out hit, range))
    100.                 {
    101.  
    102.                     partikul.Emit (3);
    103.                     // area middle point x and z, area width, area height, smoothing distance, area height adjust
    104.                     RpcraiselowerTerrainArea (hit.point, 2, 2, SmoothArea, -0.0005f);
    105.                     // area middle point x and z, area size, texture ID from terrain textures
    106.                     RpcTextureDeformation (hit.point, 2, DeformationTextureNum);
    107.                 }
    108.         }
    109.     }
    110.  
    111.  
    112.     [Command]
    113.     public void CmdraiselowerTerrainArea(Vector3 point, int lenx, int lenz, int smooth,float incdec)
    114.     {
    115.             int areax;
    116.             int areaz;
    117.             smooth += 1;
    118.             float smoothing;
    119.             int terX =(int)((point.x / myTerrain.terrainData.size.x) * xResolution);
    120.             int terZ =(int)((point.z / myTerrain.terrainData.size.z) * zResolution);
    121.             lenx += smooth;
    122.             lenz += smooth;
    123.             terX -= (lenx / 2);
    124.             terZ -= (lenz / 2);
    125.             if (terX < 0) terX = 0;
    126.             if (terX > xResolution)    terX = xResolution;
    127.             if (terZ < 0) terZ = 0;
    128.             if (terZ > zResolution)    terZ = zResolution;
    129.             float[,] heights = myTerrain.terrainData.GetHeights(terX, terZ, lenx, lenz);
    130.             float y = heights[lenx/2,lenz/2];
    131.             y += incdec;
    132.             for (smoothing=1; smoothing < smooth+1; smoothing++)
    133.             {
    134.                 float multiplier = smoothing / smooth;
    135.                 for (areax = (int)(smoothing/2); areax < lenx-(smoothing/2); areax++)
    136.                 {
    137.                     for (areaz = (int)(smoothing/2); areaz < lenz-(smoothing/2); areaz++)
    138.                     {
    139.                         if ((areax > -1) && (areaz > -1) && (areax < xResolution) && (areaz < zResolution))
    140.                         {
    141.                             heights [areax, areaz] = Mathf.Clamp((float)y*multiplier,0,1);
    142.                         }
    143.                     }
    144.                 }
    145.             }
    146.             myTerrain.terrainData.SetHeights (terX, terZ, heights);
    147.     }
    148.  
    149.  
    150.     [Command]
    151.     public void CmdTextureDeformation(Vector3 pos, float craterSizeInMeters,int textureIDnum)
    152.     {
    153.        
    154.         Vector3 alphaMapTerrainPos = GetRelativeTerrainPositionFromPos(pos, myTerrain, alphaMapWidth, alphaMapHeight);
    155.         int alphaMapCraterWidth = (int)(craterSizeInMeters * (alphaMapWidth / myTerrain.terrainData.size.x));
    156.         int alphaMapCraterLength = (int)(craterSizeInMeters * (alphaMapHeight / myTerrain.terrainData.size.z));
    157.         int alphaMapStartPosX = (int)(alphaMapTerrainPos.x - (alphaMapCraterWidth / 2));
    158.         int alphaMapStartPosZ = (int)(alphaMapTerrainPos.z - (alphaMapCraterLength/2));
    159.         float[, ,] alphas = myTerrain.terrainData.GetAlphamaps(alphaMapStartPosX, alphaMapStartPosZ, alphaMapCraterWidth, alphaMapCraterLength);
    160.         float circlePosX;
    161.         float circlePosY;
    162.         float distanceFromCenter;
    163.         for (int i = 0; i < alphaMapCraterLength; i++) //width
    164.         {
    165.             for (int j = 0; j < alphaMapCraterWidth; j++) //height
    166.             {
    167.                 circlePosX = (j - (alphaMapCraterWidth / 2)) / (alphaMapWidth / myTerrain.terrainData.size.x);
    168.                 circlePosY = (i - (alphaMapCraterLength / 2)) / (alphaMapHeight / myTerrain.terrainData.size.z);
    169.                 distanceFromCenter = Mathf.Abs(Mathf.Sqrt(circlePosX * circlePosX + circlePosY * circlePosY));
    170.                 if (distanceFromCenter < (craterSizeInMeters / 2.0f))
    171.                 {
    172.                     for (int layerCount = 0; layerCount < numOfAlphaLayers; layerCount++)
    173.                     {
    174.                         //could add blending here in the future
    175.                         if (layerCount == textureIDnum)
    176.                         {
    177.                             alphas[i, j, layerCount] = 1;
    178.                         }
    179.                         else
    180.                         {
    181.                             alphas[i, j, layerCount] = 0;
    182.                         }
    183.                     }
    184.                 }
    185.             }
    186.         }
    187.         myTerrain.terrainData.SetAlphamaps(alphaMapStartPosX, alphaMapStartPosZ, alphas);
    188.     }
    189.  
    190.  
    191. [ClientRpc]
    192.     public void RpcraiselowerTerrainArea(Vector3 point, int lenx, int lenz, int smooth,float incdec)
    193.     {
    194.  
    195.         int areax;
    196.         int areaz;
    197.         smooth += 1;
    198.         float smoothing;
    199.         int terX =(int)((point.x / myTerrain.terrainData.size.x) * xResolution);
    200.         int terZ =(int)((point.z / myTerrain.terrainData.size.z) * zResolution);
    201.         lenx += smooth;
    202.         lenz += smooth;
    203.         terX -= (lenx / 2);
    204.         terZ -= (lenz / 2);
    205.         if (terX < 0) terX = 0;
    206.         if (terX > xResolution)    terX = xResolution;
    207.         if (terZ < 0) terZ = 0;
    208.         if (terZ > zResolution)    terZ = zResolution;
    209.         float[,] heights = myTerrain.terrainData.GetHeights(terX, terZ, lenx, lenz);
    210.         float y = heights[lenx/2,lenz/2];
    211.         y += incdec;
    212.         for (smoothing=1; smoothing < smooth+1; smoothing++)
    213.         {
    214.             float multiplier = smoothing / smooth;
    215.             for (areax = (int)(smoothing/2); areax < lenx-(smoothing/2); areax++)
    216.             {
    217.                 for (areaz = (int)(smoothing/2); areaz < lenz-(smoothing/2); areaz++)
    218.                 {
    219.                     if ((areax > -1) && (areaz > -1) && (areax < xResolution) && (areaz < zResolution))
    220.                     {
    221.                         heights [areax, areaz] = Mathf.Clamp((float)y*multiplier,0,1);
    222.                     }
    223.                 }
    224.             }
    225.         }
    226.         myTerrain.terrainData.SetHeights (terX, terZ, heights);
    227.     }
    228.  
    229.  
    230.     [ClientRpc]
    231.     public void RpcTextureDeformation(Vector3 pos, float craterSizeInMeters,int textureIDnum)
    232.     {
    233.         Vector3 alphaMapTerrainPos = GetRelativeTerrainPositionFromPos(pos, myTerrain, alphaMapWidth, alphaMapHeight);
    234.         int alphaMapCraterWidth = (int)(craterSizeInMeters * (alphaMapWidth / myTerrain.terrainData.size.x));
    235.         int alphaMapCraterLength = (int)(craterSizeInMeters * (alphaMapHeight / myTerrain.terrainData.size.z));
    236.         int alphaMapStartPosX = (int)(alphaMapTerrainPos.x - (alphaMapCraterWidth / 2));
    237.         int alphaMapStartPosZ = (int)(alphaMapTerrainPos.z - (alphaMapCraterLength/2));
    238.         float[, ,] alphas = myTerrain.terrainData.GetAlphamaps(alphaMapStartPosX, alphaMapStartPosZ, alphaMapCraterWidth, alphaMapCraterLength);
    239.         float circlePosX;
    240.         float circlePosY;
    241.         float distanceFromCenter;
    242.         for (int i = 0; i < alphaMapCraterLength; i++) //width
    243.         {
    244.             for (int j = 0; j < alphaMapCraterWidth; j++) //height
    245.             {
    246.                 circlePosX = (j - (alphaMapCraterWidth / 2)) / (alphaMapWidth / myTerrain.terrainData.size.x);
    247.                 circlePosY = (i - (alphaMapCraterLength / 2)) / (alphaMapHeight / myTerrain.terrainData.size.z);
    248.                 distanceFromCenter = Mathf.Abs(Mathf.Sqrt(circlePosX * circlePosX + circlePosY * circlePosY));
    249.                 if (distanceFromCenter < (craterSizeInMeters / 2.0f))
    250.                 {
    251.                     for (int layerCount = 0; layerCount < numOfAlphaLayers; layerCount++)
    252.                     {
    253.                         //could add blending here in the future
    254.                         if (layerCount == textureIDnum)
    255.                         {
    256.                             alphas[i, j, layerCount] = 1;
    257.                         }
    258.                         else
    259.                         {
    260.                             alphas[i, j, layerCount] = 0;
    261.                         }
    262.                     }
    263.                 }
    264.             }
    265.         }
    266.         myTerrain.terrainData.SetAlphamaps(alphaMapStartPosX, alphaMapStartPosZ, alphas);
    267.     }
    268.  
    269.  
    270.     protected Vector3 GetNormalizedPositionRelativeToTerrain(Vector3 pos, Terrain terrain)
    271.     {
    272.         Vector3 tempCoord = (pos - terrain.gameObject.transform.position);
    273.         Vector3 coord;
    274.         coord.x = tempCoord.x / myTerrain.terrainData.size.x;
    275.         coord.y = tempCoord.y / myTerrain.terrainData.size.y;
    276.         coord.z = tempCoord.z / myTerrain.terrainData.size.z;
    277.         return coord;
    278.     }
    279.  
    280.     protected Vector3 GetRelativeTerrainPositionFromPos(Vector3 pos,Terrain terrain, int mapWidth, int mapHeight)
    281.     {
    282.         Vector3 coord = GetNormalizedPositionRelativeToTerrain(pos, terrain);
    283.         return new Vector3((coord.x * mapWidth), 0, (coord.z * mapHeight));
    284.     }    
    285. }
    286.  
     
  2. mischa2k

    mischa2k

    Joined:
    Sep 4, 2015
    Posts:
    4,331
    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.
     
  3. nsns

    nsns

    Joined:
    Oct 28, 2013
    Posts:
    11
    Thanks for answer
    I Understand rationale but
    How can I make that,could you give an example ?
    I am new to this topic