Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by a.lomo · Mar 11, 2015 at 04:29 PM · unity 5terrainbugsterraindataterraincollider

[SOLVED] Unity 5 - Runtime Terrain Deformation Collider Bug

It seems that to properly update a terrain and its collider in Unity 5 you have to save the scene. Similar to this issue: http://answers.unity3d.com/questions/915305/terrain-collider-bug-in-unity-5.html

The problem is that we're trying to do runtime deformation of the terrain and it properly updates it visually, but the colliders do not change. We set the terrain to not be static, but that had no effect.

Is there something that needs to be triggered programmatically on the terrain or collider for it to update from the TerrainData or is changing a TerrainCollider at runtime no longer supported?

[EDIT: This appears to be fixed in Unity 5.0.1f1]

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

4 Replies

· Add your reply
  • Sort: 
avatar image
3

Answer by StressedGamer · Mar 15, 2015 at 06:58 PM

Found a work around for anyone trying to generate the terrain once at runtime using CreateTerrainGameObject.

 GameObject terrainObj = Terrain.CreateTerrainGameObject( terrainData );
 terrainObj.transform.position = transform.position;
 terrainObj.transform.rotation = transform.rotation;
     
 float [,] heights = terrainData.GetHeights( 0, 0, terrainData.heightmapResolution, terrainData.heightmapResolution );
 terrainData.SetHeights( 0, 0, heights );

This prevented the physics geo from being mirrored around x/z.

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image a.lomo · Mar 16, 2015 at 04:51 PM 1
Share

Thanks for the suggestion.

You don't have to even create a new GameObject. It looks like setting the terrain heights for the whole terrain rebuilds the collider.

 float [,] heights = terrain.terrainData.GetHeights( 0, 0, terrain.terrainData.heightmapResolution, terrain.terrainData.heightmapResolution );
 terrain.terrainData.SetHeights( 0, 0, heights );
 

The thing is that I don't want to set it for the entire terrain, just a region of it, as this is incredibly slow.

avatar image maikkel · Mar 17, 2015 at 01:53 AM 0
Share

Yes! Thank you, I just added these two lines to my code and it works great! It doesn't even seem to have much performance impact (in my case at least...)

avatar image GXMark · Mar 23, 2015 at 10:17 PM 0
Share

Yes i've confirmed it fixes this issue but terribly slow on bigger terrains. Is this known to unity, How do we get this issue tracked?

avatar image
1

Answer by a.lomo · Mar 24, 2015 at 06:03 PM

I've submitted a bug report here: http://fogbugz.unity3d.com/default.asp?683393_bdjig2ks7rjle98v

Also here's the code I used for the bug report if anyone wants to try it:

 public class OnClickRaiseTerrain : MonoBehaviour
 {
     void Awake()
     {
         Cursor.visible = false;
         Cursor.lockState = CursorLockMode.Locked;
 
         // Create a new instance of the Terrain Data to not edit in the project
         foreach( Terrain terrain in Terrain.activeTerrains )
         {
             TerrainData inst = (TerrainData) Object.Instantiate( terrain.terrainData );
             terrain.terrainData = inst;
         }
     }
 
     void Update()
     {
         if( Input.GetMouseButtonDown( 0 ) )
         {
             RaycastHit hitInfo;
 
             if( Physics.Raycast( Camera.main.ScreenPointToRay( Camera.main.pixelRect.center ), out hitInfo ) )
             {
                 Terrain terrain = hitInfo.collider.GetComponent<Terrain>();
                 if( terrain )
                 {
                     float[,] heights = new float[,]
                     {
                         { .25f,    .5f, .25f },
                         { .5f,    1f,    .25f },
                         { .25f,    .5f, .25f },
                     };
 
                     int x, y;
                     WorldToTerrainAlphaMap( terrain, hitInfo.point, out x, out y );
                     terrain.terrainData.SetHeights( x - 1, y - 1, heights );
                 }
             }
         }
     }
 
     private static void WorldToTerrainAlphaMap( Terrain terrain, Vector3 position, out int alphaMap_x, out int alphaMap_y )
     {
         alphaMap_x = (int) (((position.x - terrain.GetPosition().x) / terrain.terrainData.size.x) * terrain.terrainData.alphamapWidth);
         alphaMap_y = (int) (((position.z - terrain.GetPosition().z) / terrain.terrainData.size.z) * terrain.terrainData.alphamapHeight);
     }
 }

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Mikael-H · May 15, 2015 at 07:32 AM 0
Share

I'm running into the same issue. I think te terrain engine in general is somewhat poorly documented and the terrain code is in need of a rehaul. Any terrafor$$anonymous$$g you want to do in runtime runs into problems like this (have you tried removing/adding trees eficciently..?) I hope your bugreport is handled! Should you find some other solution please let me know!

avatar image
0

Answer by wopper999 · Apr 10, 2015 at 12:19 PM

more of a comment than an answer but the answer from a.lomo works well. i could not find the right place to put the code in the bug report code as listed above but i did apply it to a script i found at http://answers.unity3d.com/questions/11093/modifying-terrain-height-under-a-gameobject-at-run.html the answer from Jari Kaiji is the specific one. in that script they already have heights as a float so all you have to put in is the

terrain.terrainData.GetHeights( 0, 0, terrain.terrainData.heightmapResolution, terrain.terrainData.heightmapResolution ); terrain.terrainData.SetHeights( 0, 0, heights );

and i placed that after the alpha map update around line 172. i also changed the terrain to myTerrain since its a float at the top (makes it easy so whatever your terrain name is it gets attached to the myTerrain calls and that is the way it is done in the code to keep it consistent. just as a warning though if you use any other terrain modifying script as a test you will need to place the terrain back in the myterrain in the terrain inspector. below is that code modified. as stated in the other article place this on the terrain. make sure to click the test with mouse.

 using UnityEngine;
 using System.Collections;
 
 public class RaiseLowerTerrain : MonoBehaviour
 {
     public bool TestWithMouse = false;
     public Terrain myTerrain;
     public int SmoothArea;
     private int xResolution;
     private int zResolution;
     private 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;
 
     
     
     void Start()
     {
         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 OnApplicationQuit()
     {
         if (Debug.isDebugBuild)
         {
             myTerrain.terrainData.SetHeights(0, 0, heightMapBackup);
             myTerrain.terrainData.SetAlphamaps(0, 0, alphaMapBackup);
         }
     }
     
     
     void Update()
     {
         // This is just for testing with mouse!
         // Point mouse to the Terrain. Left mouse button
         // raises and right mouse button lowers terrain.
         if (TestWithMouse == true) 
         {
             if (Input.GetMouseButtonDown (0)) 
             {
                 RaycastHit hit;
                 Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
                 if (Physics.Raycast (ray, out hit)) 
                 {
                     // area middle point x and z, area width, area height, smoothing distance, area height adjust
                     raiselowerTerrainArea (hit.point, 10, 10, SmoothArea, -0.01f); 
                     // area middle point x and z, area size, texture ID from terrain textures
                     TextureDeformation (hit.point, 10 * 2f, DeformationTextureNum);
                 }
             }
             if (Input.GetMouseButtonDown (1)) 
             {
                 RaycastHit hit;
                 Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
                 if (Physics.Raycast (ray, out hit)) 
                 {
                     // area middle point x and z, area width, area height, smoothing distance, area height adjust
                     raiselowerTerrainArea (hit.point, 10, 10, SmoothArea, 0.01f);
                     // area middle point x and z, area size, texture ID from terrain textures
                     TextureDeformation (hit.point, 10 * 2f, 0);
                 }
             }
         }
     }
     
     
     private void raiselowerTerrainArea(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);
     }
     
     private void raiselowerTerrainPoint(Vector3 point, float incdec)
     {
         int terX =(int)((point.x / myTerrain.terrainData.size.x) * xResolution);
         int terZ =(int)((point.z / myTerrain.terrainData.size.z) * zResolution);
         float y = heights[terX,terZ];
         y += incdec;
         float[,] height = new float[1,1];
         height[0,0] = Mathf.Clamp(y,0,1);
         heights[terX,terZ] = Mathf.Clamp(y,0,1);
         myTerrain.terrainData.SetHeights(terX, terZ, height);
     }
     
     protected void TextureDeformation(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);
 
         // the next two lines are added to update the terrain to fix the unity 5 terrain collidor not updating
         heights = myTerrain.terrainData.GetHeights( 0, 0, myTerrain.terrainData.heightmapResolution, myTerrain.terrainData.heightmapResolution );
         myTerrain.terrainData.SetHeights( 0, 0, heights );
     }
     
     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));
     } 
 }

there is another piece of code at http://answers.unity3d.com/questions/658026/gradual-terrain-smoothing-from-a-flat-area-at-runt.html that i would like to see if i can add to this and hopefully smooth the terrain more than the square you get from the first script. another thing i am still trying to find is a script to get the gameobjects dimensions to make the actual raise and lowering of terrain (my use is for flattening terrain when placing but also could be for basic primitive sculpting for a game also.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image $$anonymous$$ · Oct 11, 2015 at 10:48 AM 0
Share

this doesn't work. It also freezes everything up.

avatar image
0

Answer by Darkgaze · Mar 26, 2019 at 11:18 AM

For anybody looking for help, in v 2017, 2018.. to update the TerrainCollider you have to update the heights on the terraindata of both the terrainCollider and the terrain. Seems like there is a copy. Changing the terrain only will update the visualization but not the collider itself.

 terrainCollider.terrainData.setHeights(...)
 terrain.terrainData.setHeights(...)

In v2019 the terrain has been moved to GPU and the API changed, so maybe this doesn't work. Seems like there is a function to update "dirty" data.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

26 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Problem with blending two terrains together on an edge. 1 Answer

Edit Terrain at runtime 1 Answer

Possible to make custom editor script to set terrain height? 1 Answer

Object2Terrain Creates a Invalid Collider. Help please. 1 Answer

How can i get terrain data from Terrain.asset? 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges