Hello guys, I am trying to make a script that would flatten the terrain under a building when i place it ingame. I had a very hard time translating the world coordinates to the terrain coordinates and now when I have finally got it right, but I can not get it to flatten the right amount of terrain and at the right height -> I don't know how to translate the world y coords in terrain height value. Here is how I tried to do it: I got the x/y buildings' sizes in an array and then tried to flatten it out. (Buildings' sizes are in the image) What I need help with: figuring out the values i need on the lines 7,8 and 11 This is the code I use: Code (CSharp): void LevelTerrain(int x1, int y1, int yLevel) { // gets selected building's conversion to terrain coordinates // size I typed 100f because 513 was way too big // ↓↓↓↓↓↓ ↓↓↓↓↓↓↓ // | | | | int xRes = (int)(buildingsSizex[selectedBuilding] / 1000f * 100f); Debug.Log(xRes + "xRes"); int yRes = (int)(buildingsSizey[selectedBuilding] / 1000f * 100f); Debug.Log(yRes + "yRes"); //I have no idea what this variable should be // ↓↓↓↓↓ float y_Level = yLevel / 200f; //y level where the building should be //world coordinates conversion to //of where I want terrain coordinates // the building ↓↓ ↓↓↓↓ // ↓↓ | | int xBase = (int)(x1 / 1000f * 513f); Debug.Log(xBase + "xBase"); //xBase -> the point x where the Height map starts int yBase = (int)(y1 / 1000f * 513f); Debug.Log(yBase + "yBase"); //yBase -> the point y where the Height map starts float[,] heights = terrain.terrainData.GetHeights(yBase, xBase, xRes, yRes); // Heigth Map for (int i = 0; i < xRes; i++) // flatten the terrain { for (int j = 0; j < yRes; j++) { heights[j , i] = y_Level; } } terrain.terrainData.SetHeights(yBase, xBase, heights); //update the heigth map Images: sorry because of the links. Pelase look at them. https://imgur.com/rUa7hVm https://imgur.com/w4HIQZt https://imgur.com/BxijtuW If you have any ideas how to do it better please let me know. =)
I did something like this a few years ago... it was in Unity5 so I don't know how well it will behave in modern Unity with the new terrain system, but I went and extracted a .unitypackage for you and attached it. @Zer0Cool apologies for jumping your train but I still would LOVE to see your example code too!!!!!!
So finally here's my example code. Simply drag this script on the terrain and assign a primitive cube to the script that sits ontop of the terrain. The code will raise the terrain up to the height of the cube. You can even scale the cube as you like to get rectangular areas. Code (CSharp): using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// Terrain example for forum.unity.com by Zer0Cool /// </summary> public class ModifyTerrain : MonoBehaviour { [Tooltip("Assign a cube primitive here placed on the Unity terrain. You can even scale the cube if you like.")] public Transform cube; [Tooltip("Resets the terrain under the cube to zero high.")] public bool resetTerrainToZero; private Vector3 rectCenter; private float rectSizeX; private float rectSizeY; private Vector2 rectCenterMap = Vector2.zero; private int rectSizeXMap; private int rectSizeYMap; private float rectSizeHMap; private float[,] heightMap; void Start() { FlattenTerrain(); } void FlattenTerrain() { rectCenter = cube.transform.position; rectSizeX = cube.transform.localScale.x; rectSizeY = cube.transform.localScale.z; Terrain ter = GetComponent<Terrain>(); TerrainData terData = ter.terrainData; int Tw = terData.heightmapResolution; int Th = terData.heightmapResolution; heightMap = terData.GetHeights(0, 0, Tw, Th); // Determine the world coordinates float scalex = terData.heightmapResolution / terData.size.x; float scaley = terData.heightmapResolution / terData.size.z; rectCenterMap = new Vector2((int)(rectCenter.x * scalex), (int)(rectCenter.z * scaley)); rectSizeXMap = (int)((rectSizeX * scalex) / 2f); rectSizeYMap = (int)((rectSizeY * scaley) / 2f); rectSizeHMap = rectCenter.y / terData.size.y; for (int Ty = 0; Ty < Th; Ty++) { for (int Tx = 0; Tx < Tw; Tx++) { PunchOutRectangle(Ty, Tx); } } terData.SetHeights(0, 0, heightMap); } public void PunchOutRectangle(int xrow, int yrow) { if ((xrow <= (rectCenterMap.x + rectSizeXMap)) && (xrow >= (rectCenterMap.x - rectSizeXMap)) && (yrow <= (rectCenterMap.y + rectSizeYMap)) && (yrow >= (rectCenterMap.y - rectSizeYMap))) { // Raise the terrain to center of the cube heightMap[yrow, xrow] = rectSizeHMap; if (resetTerrainToZero) heightMap[yrow, xrow] = 0f; } } }