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
0
Question by lev258 · May 24, 2014 at 10:59 PM · brushessetheightscustom terrain

Terrain editor brush (Solved)

Hello. I'm working on an in-game basic terrain editor similar to Unity's. I want to be able to raise/lower the terrain with a circle brush, including properties (size, opacity), but didn't find relevant code. I got the mouse position and tried to create a radius around it for changing terrain, but only got individual spikes in a circle shaped arrangement. Any ideas?

 private void raiseTerrain(Vector3 point){
     Debug.Log(point.x);
     for (int i=0;i<=myTerrain.terrainData.size.x;i++){
         for (int j=0;j<=myTerrain.terrainData.size.z;j++){
             float xx=point.x-i;
             float zz=point.z-j;
             if(xx*xx+zz*zz<rad*rad){
                 int terX =(int)((i / myTerrain.terrainData.size.x) * xResolution);
                 int terZ =(int)((j / myTerrain.terrainData.size.z) * zResolution);
                 float y = heights[terX,terZ];
                 y += 0.001f;
                 float[,] height = new float[1,1];
                 height[0,0] = y;
                 heights[terX,terZ] = y;
                     myTerrain.terrainData.SetHeights(terX, terZ, height);
             }
         }
     }
 }

Edit: Thanks for the help alucardj, it works really nice, now I just need to modify it for my goals.

Comment
Add comment · Show 2
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 AlucardJay · May 25, 2014 at 04:31 AM 0
Share

Ins$$anonymous$$d of iterating through loops of the terrainData.size, use the heightmapData

 heightmapData = terrainData.GetHeights( 0, 0, heightmapWidth, heightmapHeight );

now you have a 2D array of the heightmapData, modify that, then reapply to the terrainData when you have finished modifying the whole circle area

 terrainData.SetHeights( 0, 0, heightmapData );

You'll need to convert your point from terrain coordinate to heightmapData coordinate. If this is what you're already doing, it's really hard to tell with that highly compacted un-commented code.

avatar image lev258 · May 25, 2014 at 10:56 AM 0
Share

Yeah, it's as you say. But still can't change the terrain in a circle shape, it's more like a line. I think I don't get the heightmapData indexes right and their meaning.

1 Reply

· Add your reply
  • Sort: 
avatar image
2

Answer by AlucardJay · May 25, 2014 at 04:08 PM

Here is an example script using the methods outlined in my comment.

For a feathered circle brush, you could calculate a modifier based on the calc.magnitude and the circleRadius, multiply paintWeight based on that modifier. I added the time between paint application to give Unity time to apply the heights, you can play with this time value or remove it.

I code easier in uJS, but if you have trouble converting it to C#, I can do that.

Warning : I use lots of comments and spaces ;)

 //-----------------------------------//
 //  RealTimeTerrainHeightPainter.js  //
 //  Written by Alucard Jay           //
 //  2014/5/26                        //
 //-----------------------------------//
 
 #pragma strict
 
 
 public var circleRadius : int = 12;
 public var paintWeight : float = 0.001;
 public var rayTimeInterval : float = 0.1;
 
 private var rayTimer : float = 0;
 private var rayHitPoint : Vector3;
 private var heightmapPos : Vector3;
 
 
 //  Persistant Functions
 //    ----------------------------------------------------------------------------
 
 
 function Start() 
 {
     GetTerrainData();
     
     ResetHeights(); // FOR TESTING, reset to flat terrain
 }
 
 
 function Update() 
 {
     rayTimer += Time.deltaTime;
     
     if ( rayTimer < rayTimeInterval )
         return;
     
     rayTimer = 0;
     
     RaycastToTerrain();
     GetHeightmapPosition();
     
     if ( Input.GetMouseButton(0) && rayHitPoint != Vector3.zero )
         PaintCircle( heightmapPos );
 }
 
 
 //  Terrain Data
 //    ----------------------------------------------------------------------------
 
 
 public var terrain : Terrain;
 private var terrainData : TerrainData;
 private var terrainSize : Vector3;
 private var heightmapWidth : int;
 private var heightmapHeight : int;
 private var heightmapData : float[,];
 
 
 function GetTerrainData()
 {
     if ( !terrain )
         terrain = Terrain.activeTerrain;
 
     terrainData = terrain.terrainData;
 
     terrainSize = terrain.terrainData.size;
 
     heightmapWidth = terrain.terrainData.heightmapWidth;
     heightmapHeight = terrain.terrainData.heightmapHeight;
 
     heightmapData = terrainData.GetHeights( 0, 0, heightmapWidth, heightmapHeight );
 }
 
 
 //  Other Functions
 //    ----------------------------------------------------------------------------
 
 
 function RaycastToTerrain() 
 {
     rayHitPoint = Vector3.zero;
     
     var hit : RaycastHit;
     var rayPos : Ray = Camera.main.ScreenPointToRay( Input.mousePosition );
 
     if ( Physics.Raycast( rayPos, hit, Mathf.Infinity ) ) // also consider a layermask to just the terrain layer
     {
         rayHitPoint = hit.point;
         Debug.DrawLine( Camera.main.transform.position, hit.point, Color.red, rayTimeInterval );
     }
 }
 
 
 function GetHeightmapPosition() 
 {
     // find the heightmap position of that hit
     heightmapPos.x = ( rayHitPoint.x / terrainSize.x ) * parseFloat( heightmapWidth );
     heightmapPos.z = ( rayHitPoint.z / terrainSize.z ) * parseFloat( heightmapHeight );
 
     // convert to integer
     heightmapPos.x = Mathf.RoundToInt( heightmapPos.x );
     heightmapPos.z = Mathf.RoundToInt( heightmapPos.z );
 
     // clamp to heightmap dimensions to avoid errors
     heightmapPos.x = Mathf.Clamp( heightmapPos.x, 0, heightmapWidth - 1 );
     heightmapPos.z = Mathf.Clamp( heightmapPos.z, 0, heightmapHeight - 1 );
 }
 
 
 function PaintCircle( point : Vector3 ) 
 {
     var x : int;
     var z : int;
     var heightX : int;
     var heightZ : int;
     var heightY : float;
     var calc : Vector2;
     
     for ( z = -circleRadius; z <= circleRadius; z ++ )
     {
         for ( x = -circleRadius; x <= circleRadius; x ++ )
         {
             // for a circle, calcualate a relative Vector2
             calc = new Vector2( x, z );
             // check if the magnitude is within the circle radius
             if ( calc.magnitude <= circleRadius )
             {
                 // is within circle, paint height
                 heightX = point.x + x;
                 heightZ = point.z + z;
                 
                 // check if heightX and Z is within the heightmapData array size
                 if ( heightX >= 0 && heightX < heightmapWidth && heightZ >= 0 && heightZ < heightmapHeight )
                 {
                     // read current height
                     heightY = heightmapData[ heightZ, heightX ]; // note that in heightmapData, X and Z are reversed
                     
                     // add paintWeight to the current height
                     heightY += paintWeight;
                     
                     // update heightmapData array
                     heightmapData[ heightZ, heightX ] = heightY;
                 }
             }
         }
     }
     
     // apply new heights to terrainData
     terrainData.SetHeights( 0, 0, heightmapData );
 }
 
 
 function ResetHeights() // FOR TESTING, reset to flat terrain
 {
     var x : int;
     var z : int;
     
     for ( z = 0; z < heightmapHeight; z ++ )
     {
         for ( x = 0; x < heightmapWidth; x ++ )
         {
             heightmapData[ z, x ] = 0;
         }
     }
     
     terrainData.SetHeights( 0, 0, heightmapData );
 }
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

21 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

Related Questions

Problem detail resolution per patch. 2 Answers

Terrain generation [2D,C#]? 0 Answers

SetHeights to a Negative 1 Answer

terraindata.setheight as a brush for runtime terrain editing 1 Answer

Prefab brushes disappear when I build a game 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