- Home /
Convert player world position into terrain detail layer coordinates (GetDetailLayer)
I've found one or two answers on this but didn't fully understand them. All i have is a player on top of the terrain and i just want to remove some details/grass if the player is on that position in the terrain. I'm currently using GetDetailLayer to get the detail information of the terrain (returns a int map[x,y]). What i need is to convert the player world position into this X, Y coordinate in the terrain and to finally set map[x,y] = 0 to eliminate the detail/grass. Any help?
Not a definitive answer (since I don't use terrain much), but you should just be able to use division to try and figure out where you are.
If you have a 100x100 terrain that is centered at 0,0 (so it goes from -50,-50 to +50,+50 in world space). The map your terrain is based on is a 200x200 grid. You just need to grab the players world positions and you can figure out where they are in terms of percentages.
As a rough guide, your coordinates are...
gridx = ((playerx - world$$anonymous$$imumx) / worldwidth) * gridwidth
So if the user is at 20,40,5, their x position in terrain space should be (x - $$anonymous$$x) / world-space-width, or (20 - -50) / 100, which is 70/100, which is 0.7 - 70% across the grid. $$anonymous$$ultiply that by the width of your terrain detail layer (200) and you know the player is at an x of 140 in grid space.
You can do the same thing for Y - ((40 - -50) / 100) * 200, which is 180.
doesn't work, i'm using a terrain with 30 width and height, with position at x = -15 and z = -15. So in this case goes from -15,-15 to +15,+15. Then i'm using these formulas:
vecRet.x = ((playerPos.x - terPos.x) / ter.terrainData.size.x) ter.terrainData.alphamapWidth; vecRet.z = ((playerPos.z - terPos.z) / ter.terrainData.size.z) ter.terrainData.alphamapHeight;
map[(int)vecRet.x, (int)vecRet.z] = 0
Im not au fait with terrains in unity but I assume that each tile is of equal size right?
What do you mean by 'doesn't work'? You aren't getting an appropriate x & y coordinate? Or is the coordinate valid, but your changes to the map aren't working?
Answer by Serge144 · Aug 13, 2019 at 09:44 PM
I got it to work :) I basically used this: (from some other answer)
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.z - terPosition.z) / ter.terrainData.size.z) * ter.terrainData.alphamapHeight;
return vecRet;
}
and then, to test, you need to clear some good amount of area around the position in the terrain to see results visually (because clearing only one pixel won't make a difference visually if you have tons of grass), and if the grass is nicely dense in the map then you'll see even more difference. I implemented this to cover the area based on the position obtained from the first block of code:
private void coverArea(int x, int y, int range) {
int xmin = x - range;
int ymin = y - range;
int xmax = x + range;
int ymax = y + range;
for (int i = xmin; i <= xmax; i++) {
for (int j = ymin; j <= ymax; j++) {
map[j, i] = 0;
}
}
t.terrainData.SetDetailLayer(0, 0, 0, map);
}
This cover area doesn't check boundaries (when the player is in the corner) so it will try to cover some out of index coordinates, but it will only throw an error and won't crash your game, eventually this should be checked as well. Terrain settings were: Width 30, length 30, position x= -15 and y = -15 (so it goes from -15 -15 to +15 +15 (because terrain origin is on bottom left corner) and resolution was 512.
worked for me too but I had to change it to:
vecRet.x = ((wordCor.x - terPosition.x) / t.terrainData.size.x) * t.terrainData.detailWidth;
vecRet.z = ((wordCor.z - terPosition.z) / t.terrainData.size.z)* t.terrainData.detailHeight;
Answer by fenderrex · Apr 22 at 02:07 AM
void OnDrawGizmos()
{//draws Gizmos on the terrain using terrain data-Rex
//use small terrain
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)
{
// not sure why the gizmo y-heights are scaled out from 0,0 (about 5X) when doing it this way.
// Uncomment this and comment the second one to see:
//Vector3 pivot = new Vector3(i, terrain.terrainData.GetHeight(i, k), k);
// this way fixes it (pretty much)--WHY??
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);
}
}
}
Your answer
Follow this Question
Related Questions
Convert terrain map coordinates (GetDetailLayer) into world position 0 Answers
terrainData.SetHeightsDelayLOD seem to have no effect and i dont know why. 1 Answer
What causes this terrain behavior? 1 Answer
copy smaller size terrain's data, and seet the heights on bigger Terrain at click position 0 Answers
seperation of prefabs with two dimensional terrain generation 0 Answers