Creating a map editor

Currently I’m building my map by adding and aligning tiles to the scene. I’d like to have something like this, where I can grab vertices and adjust the height to create a terrain.

Can you please help me make a small start? I have no idea how this is done. Is this at runtime? If so, how do I apply the changes to the scene? Thanks

As a design issue, this question is probably a better fit on Unity Forums than Unity Answers. But since your explicit question is about a starting point, I’ll give you my 2 cents worth. What you are trying to do is not a beginner topic. Here is how I might suggest you approach the problem.

At this point, you should understand how to create and manipulate meshes. The next steps will depend on your UI and deal with user input.

Here is a bit of sample source to get you started. The mesh generation is a quick cut down of the CreatePlane editor script. This is a runtime only script. To use:

  • Add a directional light
  • Create a diffuse material (with or without a texture)
  • Add the following script to an empty game object
  • Drag and drop the material on the ‘mat’ variable
  • Run the app. Click on the terrain to raise the nearest vertex.

Note this is just some quick and dirty sample source to get you over some rough areas. You should study and understand it, and don’t skip the steps above to gain the understanding of meshes you will need to expand on this code.

using UnityEngine;
using System.Collections;

public class PlaneTerrain : MonoBehaviour
{
	public Material mat;
	public int widthSegments = 21;
	public int lengthSegments = 21;
	public float width = 10.0f;
	public float length = 10.0f;
	public float lift = 1.0f;

	private GameObject plane;
	private Mesh m;
	private Vector3[] vertices;
	private int[] triangles;
	
	void Start() {
		GenerateMesh();
	}

	void GenerateMesh()
	{
		widthSegments = Mathf.Clamp(widthSegments, 1, 254);
		lengthSegments = Mathf.Clamp(lengthSegments, 1, 254);
		plane = new GameObject();
		
		plane.name = "Plane Terrain";
		plane.transform.position = Vector3.zero;
		
		MeshFilter meshFilter = (MeshFilter)plane.AddComponent<MeshFilter>();
		plane.AddComponent<MeshRenderer>();
		plane.renderer.material = mat;

		m = new Mesh();

		int hCount2 = widthSegments+1;
		int vCount2 = lengthSegments+1;
		int numTriangles = widthSegments * lengthSegments * 6;
		int numVertices = hCount2 * vCount2;
		
		vertices = new Vector3[numVertices];
		Vector2[] uvs = new Vector2[numVertices];
		triangles = new int[numTriangles];
		
		int index = 0;
		float uvFactorX = 1.0f/widthSegments;
		float uvFactorY = 1.0f/lengthSegments;
		float scaleX = width/widthSegments;
		float scaleY = length/lengthSegments;
		for (float y = 0.0f; y < vCount2; y++)
		{
			for (float x = 0.0f; x < hCount2; x++)
			{
				vertices[index] = new Vector3(x*scaleX - width/2f, 0.0f, y*scaleY - length/2f);
				uvs[index++] = new Vector2(x*uvFactorX, y*uvFactorY);
			}
		}
		
		index = 0;
		for (int y = 0; y < lengthSegments; y++)
		{
			for (int x = 0; x < widthSegments; x++)
			{
				triangles[index]   = (y     * hCount2) + x;
				triangles[index+1] = ((y+1) * hCount2) + x;
				triangles[index+2] = (y     * hCount2) + x + 1;
				
				triangles[index+3] = ((y+1) * hCount2) + x;
				triangles[index+4] = ((y+1) * hCount2) + x + 1;
				triangles[index+5] = (y     * hCount2) + x + 1;
				index += 6;
			}
			
			m.vertices = vertices;
			m.uv = uvs;
			m.triangles = triangles;
			m.RecalculateNormals();
		}
		
		meshFilter.sharedMesh = m;
		m.RecalculateBounds();
		
		plane.AddComponent<MeshCollider>();
	}

	void Update() {

		if (Input.GetMouseButtonDown (0)) {
			Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
			RaycastHit hit;
			if (plane.collider.Raycast(ray, out hit, Mathf.Infinity)) {
		
				int tri = hit.triangleIndex * 3;
				Debug.Log (tri);
				float dist1 = Vector3.Distance (hit.point, plane.transform.TransformPoint (vertices[triangles[hit.triangleIndex * 3]]));
				float dist2 = Vector3.Distance (hit.point, plane.transform.TransformPoint (vertices[triangles[hit.triangleIndex * 3 +1]]));
				if (dist2 < dist1) {
					dist1 = dist2;
					tri = hit.triangleIndex * 3 + 1;
				}
				dist2 = Vector3.Distance (hit.point, plane.transform.TransformPoint (vertices[triangles[hit.triangleIndex * 3 + 2]]));
				if (dist2 < dist1) {
					tri = hit.triangleIndex * 3 + 2;
				}
				vertices[triangles[tri]].y += lift;

				m.vertices = vertices;
				m.RecalculateBounds();
				m.RecalculateNormals();
			}
		}
	}
}