zoukankan      html  css  js  c++  java
  • Unity 自定义地形编辑器开发(一.快速创建基层模型地图)

    废话不多说直接先看效果

    下面是步骤

      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;
        }
    }
    

      

  • 相关阅读:
    html5学习系列之ef类标签
    html5学习系列之cd标签
    Java学习系列——xml学习基础
    html5学习系列——b标签
    为什么我要使用Linux,使用Linux的十个理由。
    设置Linux系统的空闲等待时间TMOUT的方法和Linux反空闲设置的两种方法
    创建动态MSSQL数据库表的方法
    SQL SERVER 自增列的方法
    XtraBackup构建MySQL主从环境的方法
    如何查看MySQL执行计划呢?
  • 原文地址:https://www.cnblogs.com/littlebao/p/12387703.html
Copyright © 2011-2022 走看看