Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Realtime Unity Terrain Manipulation Possible?

Discussion in 'Scripting' started by DP007, Apr 26, 2011.

  1. DP007

    DP007

    Joined:
    Jan 23, 2009
    Posts:
    24
    Hey guys,

    I'm trying to manipulate the terrain heights in realtime. Currently, I'm using the SetHeights function from the terrain but that works so slowly that this is no opportunity to use. Is there another way for terrain manipulation via script in realtime? The raise/lower function in the unity terrain editor also does it really fast without any latencies. Maybe it's so slow, because the terrain collider is being recalculated at each time. Is there a way to prevent the collider from being recalculated?

    Thanks in advance.
     
  2. Jacob-Williams

    Jacob-Williams

    Joined:
    Jan 30, 2009
    Posts:
    267
    @DP007 - You don't want to recalculate the mesh collider every frame - that is probably where your problem is. If you are using SetHeights while the mouse button is down, wait until that button is released to recalculate the mesh. That should solve your problem.
     
  3. DP007

    DP007

    Joined:
    Jan 23, 2009
    Posts:
    24
    Thanks for your reply.
    But how do I prevent the SetHeights function from recalculating the collider? I think it does it automatically.
    I also removed the collider from the terrain but that didn't change anythink. Still sucking performance at around 20-30 fps.
    Why is the unity terrain editor so fast in manipulating terrain heights compared to in game terrain manipulation?
     
  4. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Are you using SetHeights for the entire terrain, or just the part you're updating?

    --Eric
     
  5. DP007

    DP007

    Joined:
    Jan 23, 2009
    Posts:
    24
    No, I'm not using SetHeights for the entire terrain. For your understanding: We are developing a game where you can dig with an excavator into the terrain. Thus, the area of terrain manipulation is relatively small and I'm just setting this area with SetHeights. But it doesn't really matter how big the area is, the performance is still crappy when setting only one heightmap value at a time. The terrain size is 100x100 and heightmap size 512, which isn't that much. Any further ideas?

    Thanks.
     
  6. Dragonsnare0

    Dragonsnare0

    Joined:
    Nov 28, 2011
    Posts:
    6
    Hi,

    I'm new to Unity 3D but am a long time game developer/coder. I'm interested in seeing if this have been figured out. I'm currently working on a project that utilizes the same feature.

    Thanks.
     
  7. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    OK, to answer this... Yes, redoing the entire terrain is bad.

    Create a new scene and throw this script on the camera. (remember to leave it as the main camera.)

    Code (csharp):
    1.  
    2. private var terrain : Terrain;
    3. var resolution : int = 513;
    4. var doAll : boolean = false;
    5.  
    6. function Start () {
    7.     FixResoloution();
    8.     var tdata = new TerrainData();
    9.     var size : float= 100.0 / resolution * 32.0;
    10.     tdata.size = new Vector3(size, 20, size);
    11.     tdata.heightmapResolution = resolution;
    12.     terrain = Terrain.CreateTerrainGameObject(tdata).GetComponent(Terrain);
    13.     var t = Camera.main.transform;
    14.     t.position = Vector3(120,31,-5);
    15.     t.localEulerAngles = Vector3(27,310,0);
    16.     var lo = new GameObject();
    17.     var l : Light= lo.AddComponent(Light);
    18.     l.type = LightType.Directional;
    19.     lo.transform.localEulerAngles = Vector3(40,20,0);
    20. }
    21.  
    22. function Update(){
    23.     var tdata : TerrainData = terrain.terrainData;
    24.     var width = tdata.heightmapWidth;
    25.     var height = tdata.heightmapHeight;
    26.     if(!doAll){
    27.         width /= 8;
    28.         height /= 8;
    29.     }
    30.     var heights : float[,]=new float[height, width];
    31.     for(var y=0; y<height; y++){
    32.         for(var x=0; x<width; x++){
    33.             heights[y,x]=Random.value;
    34.         }
    35.     }
    36.     tdata.SetHeights(0,0,heights);
    37. }
    38.  
    39. function FixResolution(){
    40.     var c = 0;
    41.     while(resolution > 0){
    42.         resolution = resolution >> 1;
    43.         c++;
    44.     }
    45.     resolution =Mathf.Pow(2, c - 1) + 1;
    46.     if(resolution > 513) resolution = 513;
    47.     if(resolution < 33) resolution = 33;
    48. }
    49.  
    I am sure it could be spruced up, but it will give the general feel. In the Editor, set the resolution to 512 and press play. You will see a terrain with a small section of it changing. Click the check box to do it all... and it bogs the entire machine down.

    The answer to your question: Yes, it is possible, but you have to program it right.
     
  8. Dragonsnare0

    Dragonsnare0

    Joined:
    Nov 28, 2011
    Posts:
    6
    Very cool thanks.