Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 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
7
Question by user-614 (google) · Dec 20, 2009 at 06:44 PM · terrain

How to translate WORLD coordinates to TERRAIN coordinates?

Recently I've begun messing around with altering the terrain in real-time. One of the hiccups I've run into is that world coordinates are not the same as terrain coordinates (obviously). How can I take a position in the world and translate it to the nearest point on the terrain that I can then alter the height of? I hope my question is clear enough. Any advice is appreciated!

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

5 Replies

· Add your reply
  • Sort: 
avatar image
14
Best Answer

Answer by duck · Dec 20, 2009 at 07:15 PM

First, subtract the terrain gameobject's world position, then divide by your terrain's size (which you can access in terrainData.size). This will give you a position with values somewhere in the range of zero to one.

You can then multiply this by your heightmap resolution (using the terrainData heightmapWidth and heightmapHeight variables), and then convert to integers to find the correct heightmap array position to feed into the GetHeights and SetHeights functions.

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 Yanger_xy · Mar 12, 2011 at 12:30 PM 0
Share

private Vector3 ConvertWordCor2TerrCor(Vector3 wordCor) { Vector3 vecRet = new Vector3(); Terrain ter = Terrain.activeTerrain; Vector3 terPosition = ter.transform.position; vecRet.x = ((wordCor.x - terPosition.x) / ter.terrainData.size.x) ter.terrainData.alphamapWidth; vecRet.z = ((wordCor.y - terPosition.z) / ter.terrainData.size.z) ter.terrainData.alphamapHeight; return vecRet; } Is this right? or i should change it like this: vecRet.x **= ((wordCor.x - terPosition.x) / ter.terrainData.size.x) ter.terrainData.alphamapWidth;

avatar image vbs · Mar 12, 2015 at 06:36 PM 0
Share

How do you calculate the "height map resolution"? If I get the resolution like this: tData = terrain.terrainData; xRes = tData.heightmapWidth; yRes = tData.heightmapHeight; Then what do I do with ((point.x - terrainPosition.x) / terrainSize.x) * ...?

avatar image Radivarig vbs · Jul 06, 2020 at 01:21 PM 0
Share

@vbs terrain.terrainData.heightmapResolution

avatar image
3

Answer by Baalhug · Nov 02, 2018 at 12:08 AM

The terrain is a bidimensional array of float numbers between 0 and 1, where 0 is the lowest height and 1 is the highest. So 0.5 will be the half height defined in your Terrain Height variable. If you have defined a height of 300, 0.5 will be 150 height in world coordinates, 0.6 will be 180, and so on.

This way an array like this:

0, 0.5, 0

0.5, 1, 0.5

0, 0.5, 0

would make a romboid pyramid out of your terrain independent of your terrain object dimensions in world coordinates. Unity developers called heightmapWidth and heightmapHeight variables in heightmap resolution but heightmapHeight should be heightmapLength as they refer to the numbers of points in bidimensional array, and height is actually the value of each float on that array. Anyway in our example both variables have a value of 3, because our terrain has 3 x 3 values for heights. That is a very bad resolution but is enough to explain and understand. The higher resolution the most height points you will have in your terrain, the most precise will be your terrain contour and the larger will be the file.

Now imagine you raycast on the top of this pyramid knowing the gameobject terrain is 500 x 500 in world coordinates, you will have a point of collision in world coordinates x=250 z=250, assuming the terrain world position is Vector3(0, 0, 0). Then you can calculate the relation in world coordinates and pass it to terrain coordinates or viceversa. To know wich point of the terrain you have to edit:

 //% of terrain x = (x point of raycast collision - x position of your terrain object) / x total width of terrain
 //same with z
 
 // raycast object is called ray
 
 Terrain ter = GetComponent<Terrain>(); // assuming this script is attached to the terrain
 float relativeHitTerX = (ray.point.x  - transform.position.x) / ter.terrainData.size.x;
 float relativeHitTerZ = (ray.point.z - transform.position.z) / ter.terrainData.size.z;

 // you have a number between 0 and 1 where your terrain has been hit (multiplied by 100 it would be the percentage of width and length)

 relativeTerCoordX = ter.terrainData.heightmapWidth * relativeHitTerX;
 relativeTerCoordZ = ter.terrainData.heightmapHeight * relativeHitTerZ;
 
 // now you have the relative point of your terrain, but you need to floor this because the number of points on terrain are integer

 int hitPointTerX = Mathf.floorToInt(relativeTerCoordX);
 int hitPointTerZ = Mathf.floorToInt(relativeTerCoordZ);
 
 //Now you can use this point to edit it using SetHeights

 float[,] heights = ter.terrainData.GetHeights(); 
 heights[hitPointTerx, hitPointTerZ] = heights[hitPointTerx, hitPointTerZ] - (10/ter.terrainData.size.y)
 ter.terrainData.SetHeights(0, 0, heights);

 // this will lower that terrain point 10% of max height of that terrain object, if you want a "crater" effect you can get and edit the points surrounding your impact point and substract a little less, like (7/ter.terrainData.size.y) for example


Check out this syntax, they can have errors as I didn't write them in editor

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 Linus · Sep 28, 2019 at 03:04 AM 0
Share

Here is an updated and cleaned up version of the sample code

     public Terrain terrain;
     TerrainData td;
     private void Start( )
     {
        td = terrain.terrainData;
     }

  
     Ray ray = new Ray(transform.position, -transform.up);

     RaycastHit hit;
     if ( Physics.Raycast( ray, out hit, 50f ) )
     {
        
         float relativeHitTerX = (hit.point.x  - terrain.transform.position.x) / td.size.x;
         float relativeHitTerZ = (hit.point.z - terrain.transform.position.z) / td.size.z;

         float relativeTerCoordX = td.heightmapResolution * relativeHitTerX;
         float relativeTerCoordZ = td.heightmapResolution * relativeHitTerZ;

         int hitPointTerX = $$anonymous$$athf.FloorToInt(relativeTerCoordX);
         int hitPointTerZ = $$anonymous$$athf.FloorToInt(relativeTerCoordZ);

         float[,] heights = td.GetHeights(0, 0, td.heightmapResolution ,td.heightmapResolution);
         
         heights[ hitPointTerZ, hitPointTerX ] = heights[ hitPointTerZ, hitPointTerX ] * 1.05f;
         td.SetHeights( 0, 0, heights );

// Debug.DrawLine( transform.position, hit.point, Color.red, 5f ); // Debug.Log( "Hit " + hit.point.x + " " + hit.point.z + " Relative: " + relativeHitTerX + " " + relativeHitTerZ );

     }
avatar image
0

Answer by darkmath · Jan 12, 2010 at 03:03 PM

You could also do a terrain.collider.Raycast:

RaycastHit intersection = new RaycastHit();
Ray originUp = new Ray(new Vector3(0,0,0), Vector3.up);
terrain.collider.Raycast(originUp, out intersection, 100000.0f);
if (intersection.collider != null)
{ ball.transform.position = intersection.point;
ball.rigidbody.position = intersection.point;
}

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 Owen-Reynolds · Apr 22, 2011 at 07:45 PM 1
Share

That just gives a world position again. Terrain position is the little blue squares when you paint it.

avatar image
0

Answer by Yanger_xy · Mar 12, 2011 at 12:30 PM

private Vector3 ConvertWordCor2TerrCor(Vector3 wordCor)
{
    Vector3 vecRet = new Vector3();
    Terrain ter = Terrain.activeTerrain;
    Vector3 terPosition =  ter.transform.position;
    vecRet.x = ((wordCor.x - terPosition.x) / ter.terrainData.size.x) * ter.terrainData.alphamapWidth;
    vecRet.z = ((wordCor.y - terPosition.z) / ter.terrainData.size.z) * ter.terrainData.alphamapHeight;
    return vecRet;
}

Is this right? or i should change it like this: vecRet.x *= ((wordCor.x - terPosition.x) / ter.terrainData.size.x) ter.terrainData.alphamapWidth; vecRet.z = ((wordCor.y - terPosition.z) / ter.terrainData.size.z) * ter.terrainData.alphamapHeight;

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
avatar image
0

Answer by fenderrex · Apr 22 at 02:03 AM

draws Gizmos using TerrainData on Terrain

 void OnDrawGizmos()
 {
     Terrain terrain = GetComponent<Terrain>();
     Vector3 terrainSize = terrain.terrainData.size;

     for (int i = 0; i < terrain.terrainData.heightmapResolution; i += 1) // use steps of more than 1 for smoother interaction in editor
     {
         for (int k = 0; k < terrain.terrainData.heightmapResolution; k += 1)
         {
             
             Vector3 pivot = new Vector3(k, terrain.terrainData.GetHeight(k , i ), i);

             float x = pivot.x / (terrainSize.x);
             float z = pivot.z / (terrainSize.z );
             Vector3 interpolatedNormal = terrain.terrainData.GetInterpolatedNormal(x, z);
             
             GUI.color = Color.blue;
             pivot  = terrain.transform.position+ new Vector3(pivot.x / terrain.terrainData.heightmapResolution * terrainSize.x, pivot.y, pivot.z / terrain.terrainData.heightmapResolution * terrainSize.y);
             Gizmos.DrawSphere(pivot, 0.2f);
            Gizmos.color = Color.cyan;
             Gizmos.DrawRay(pivot, interpolatedNormal * rayScale);
         }
     }
 }
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

7 People are following this question.

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

Related Questions

The name 'Joystick' does not denote a valid type ('not found') 2 Answers

(script) how to get terrain to turn into blocks 0 Answers

Instantiating a object in a certain position.. 1 Answer

Modifying Terrain Splat Texture at Runtime 2 Answers

Seamless infinte terrain 1 Answer


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