废话不多说直接先看效果

下面是步骤
1.弹窗
效果:

代码:
public class InputImageToEditor : EditorWindow
{
public static InputImageToEditor instance;
void OnEnable() { instance = this; }
void OnDisable() { instance = null; }
public Texture icon;
string mapWidth="10", mapLength="0", mapPd="0";
string savePath;
string mapName;
bool IsDefault = true;
void OnGUI()
{
byte[] bytes = File.ReadAllBytes("Assets/Texture/LOGO.png");
Texture2D texture = new Texture2D(200, 200);
texture.LoadImage(bytes);
icon = texture;
EditorGUILayout.Space();
GUILayout.BeginVertical();
GUILayout.Space(10);
GUILayout.Label(icon, GUILayout.Width(100), GUILayout.Height(100));//绘制图标
GUI.skin.label.fontSize = 14;
GUI.skin.label.fontStyle = FontStyle.Bold;
GUILayout.Label("输入相应参数");
GUI.skin.label.fontStyle = FontStyle.Normal;
GUI.skin.label.fontSize = 12;
GUILayout.Space(10);
mapName = EditorGUILayout.TextField("设置地图名字", mapName);
GUILayout.Space(10);
mapWidth = EditorGUILayout.TextField("设置地图宽度", mapWidth);
GUILayout.Space(10);
EditorGUI.BeginDisabledGroup(true); //如果nextPath == null 为真,在Inspector面板上显示,承灰色(即不可操作)
mapLength = EditorGUILayout.TextField("设置地图长度", mapWidth);
EditorGUI.EndDisabledGroup();
GUILayout.Space(10);
IsDefault = EditorGUILayout.Toggle("是否使用默认定点密度", IsDefault);
if (!IsDefault)
{
GUILayout.Space(10);
mapPd = EditorGUILayout.TextField("设置地图定点密度(建议为宽度X5)", mapPd);
}
else
{
mapPd = ""+int.Parse(mapWidth) * 5;
}
GUILayout.Space(10);
if (GUILayout.Button("选择保存文件夹"))
{
savePath = EditorUtility.OpenFolderPanel("选择保存的文件夹", "Assets/", "");
}
GUILayout.Space(10);
GUILayout.EndVertical();
GUILayout.BeginHorizontal();
if (GUILayout.Button("确定"))
{
if (mapWidth.Length > 0)
{
XLZTerrainEditor.OpenImage(int.Parse(mapWidth), uint.Parse(mapPd), savePath,mapName);
instance.Close();
EditorUtility.DisplayDialog("创建结果", "创建成功", "确定");
}
else
{
Debug.LogError("请输入相应的值");
}
}
GUILayout.Space(120);
if (GUILayout.Button("取消"))
{
instance.Close();
}
GUILayout.EndHorizontal();
}
}
2.调用弹窗选择图片并读取
效果

代码:
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
using System.Windows;
public class XLZTerrainEditor
{
[MenuItem("Tools/创建基本地形", false, 21)]
static void CreateBasicTerrain()
{
EditorWindow.GetWindow<InputImageToEditor>(false, "InputImageToEditor", true).Show();
}
/// <summary>
/// 发起Win会话读取选择的图片
/// </summary>
public static void OpenImage(int mapWidth,uint mapPD,string savePath,string mapName)
{
string path= EditorUtility.OpenFilePanelWithFilters("选择文件", "C:\Users\Administrator\Desktop", new string[] { "图片格式", "png,jpg,jpeg", "All files", "*" });
//创建文件读取流
FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
fileStream.Seek(0, SeekOrigin.Begin);
//创建文件长度缓冲区
byte[] bytes = new byte[fileStream.Length];
//读取文件
fileStream.Read(bytes, 0, (int)fileStream.Length);
//释放文件读取流
fileStream.Close();
fileStream.Dispose();
fileStream = null;
Texture2D texture = new Texture2D(1, 1);
bool isload = texture.LoadImage(bytes);
//Sprite tempSp = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0, 0));
//GameObject.Find("TestImage").GetComponent<Image>().sprite = tempSp;
//GameObject tGO = new GameObject("testTerrain");
//DrawMesh(tGO, texture, mapWidth, mapPD);
XLZMapMesh xLZMap = new XLZMapMesh(mapName, texture, savePath);
xLZMap.CreatMesh(mapWidth, mapWidth, mapPD, mapPD, -10, 10);
}
}
3.创建网格地图模型
代码:
using UnityEngine;
using System.Collections;
using UnityEditor;
using System.IO;
public class XLZMapMesh
{
private GameObject mMesh;
private Material mMaterial;
private Texture2D mHeightImage;
private Vector2 size;//长度和宽度
public float minHeight = -10;//最小高度
public float maxHeight = 10;//最大高度
private Vector2 segment;//长度的段数和宽度的段数
private float unitH;//最小高度和最大高度只差,值为正
private Vector3[] vertexes;//顶点数
private Vector2 uvs;//uvs坐标
private int[] triangles;//三角形索引
private string Name;
private string SavePath="";
public XLZMapMesh(string name, Texture2D hMap,string savePath)
{
Name = name;
mHeightImage = hMap;
if (savePath!=null)
{
SavePath = savePath;
}
}
public void CreatMesh(float width, float height, uint segmentX, uint segmentY, int min, int max)
{
size = new Vector2(width, height);
maxHeight = max;
minHeight = min;
unitH = maxHeight - minHeight;
segment = new Vector2(segmentX, segmentY);
mMesh = new GameObject();
mMesh.name = Name;
computeVertexes();
DrawMesh();
}
private void computeVertexes()
{
int sum = Mathf.FloorToInt((segment.x + 1) * (segment.y + 1));//顶点总数
float w = size.x / segment.x;//每一段的长度
float h = size.y / segment.y;
GetTriangles();
int index = 0;
vertexes = new Vector3[sum];
for (int i = 0; i < segment.y + 1; i++)
{
for (int j = 0; j < segment.x + 1; j++)
{
vertexes[index] = new Vector3(j * w, GetHeight(mHeightImage,new Vector2(i/segment.x, j/ segment.y))* unitH, i * h);
index++;
}
}
}
private void DrawMesh()
{
Mesh mesh = new Mesh();
mesh.name = Name;
mMesh.AddComponent<MeshFilter>();//网格
mMesh.AddComponent<MeshRenderer>();//网格渲染器
mMaterial = new Material(Shader.Find("MTE/Legacy/4 Textures/Diffuse"));//材质
mMesh.GetComponent<Renderer>().material = mMaterial;
/*设置mesh*/
mesh.Clear();//更新
mesh.vertices = vertexes;
//mesh.uv
mesh.triangles = triangles;
mesh.RecalculateNormals();
mesh.RecalculateBounds();
mMesh.GetComponent<MeshFilter>().mesh= mesh;
//SaveAll(mesh, mMaterial);
}
private void SaveAll(Mesh mesh, Material material)
{
string localPath = SavePath.Substring(SavePath.IndexOf("Assets"));
localPath += "/" + Name;
Directory.CreateDirectory(localPath);
Object prefabObj = PrefabUtility.SaveAsPrefabAssetAndConnect(mMesh,localPath + "/" + Name + ".prefab",InteractionMode.AutomatedAction);
AssetDatabase.CreateAsset(mMaterial, localPath + "/" + Name + ".mat");
AssetDatabase.CreateAsset(mesh, localPath + "/" + Name + ".asset");
}
private int[] GetTriangles()
{
int sum = Mathf.FloorToInt(segment.x * segment.y * 6);//三角形顶点总数
triangles = new int[sum];
uint index = 0;
for (int i = 0; i < segment.y; i++)
{
for (int j = 0; j < segment.x; j++)
{
int role = Mathf.FloorToInt(segment.x) + 1;
int self = j + (i * role);
int next = j + ((i + 1) * role);
//顺时针
triangles[index] = self;
triangles[index + 1] = next + 1;
triangles[index + 2] = self + 1;
triangles[index + 3] = self;
triangles[index + 4] = next;
triangles[index + 5] = next + 1;
index += 6;
}
}
return triangles;
}
private static float GetHeight(Texture2D texture, Vector2 uv)
{
if (texture != null)
{
Color c = GetColor(texture, uv);
return c.r - 0.5f;
}
else
{
return 0.5f;
}
}
private static Color GetColor(Texture2D texture, Vector2 uv)
{
Color color = texture.GetPixel(Mathf.FloorToInt(texture.width * uv.x), Mathf.FloorToInt(texture.height * uv.y));
return color;
}
}