廢話不多說直接先看效果

下面是步驟
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;
}
}
