using System.Collections; using System.Collections.Generic; using System.IO; using System.Text; using UnityEngine; using UnityEditor; namespace MyFrameworkPure { /// /// 批量生成预设窗口 /// public class BatchCreatePrefabWindow : EditorWindow { [MenuItem("Tools/批量生成Prefab")] static void AddWindow() { //创建窗口 BatchCreatePrefabWindow window = (BatchCreatePrefabWindow)EditorWindow.GetWindow(typeof(BatchCreatePrefabWindow), false, "批量生成Prefab"); window.Show(); } //输入文字的内容 private string PrefabPath = "Assets/Resources/"; private string ObjPath = @"Assets/Obj/"; GameObject[] selectedGameObjects; [InitializeOnLoadMethod] public void Awake() { OnSelectionChange(); } void OnGUI() { GUIStyle text_style = new GUIStyle(); text_style.fontSize = 15; text_style.alignment = TextAnchor.MiddleCenter; EditorGUILayout.BeginHorizontal(); GUILayout.Label("Prefab导出路径:"); PrefabPath = EditorGUILayout.TextField(PrefabPath); if (GUILayout.Button("浏览")) { EditorApplication.delayCall += OpenPrefabFolder; } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Label(" Obj导出路径:"); ObjPath = EditorGUILayout.TextField(ObjPath); if (GUILayout.Button("浏览")) { EditorApplication.delayCall += OpenObjFolder; } EditorGUILayout.EndHorizontal(); GUILayout.Label("当前选中了" + selectedGameObjects.Length + "个物体", text_style); if (GUILayout.Button("如果包含动态创建的Mesh,请先点击生成Obj", GUILayout.MinHeight(20))) { foreach (GameObject m in selectedGameObjects) { CreateObj(m); } AssetDatabase.Refresh(); } if (GUILayout.Button("生成当前选中物体的Prefab", GUILayout.MinHeight(20))) { if (selectedGameObjects.Length <= 0) { //打开一个通知栏 this.ShowNotification(new GUIContent("未选择所要导出的物体")); return; } if (!Directory.Exists(PrefabPath)) { Directory.CreateDirectory(PrefabPath); } foreach (GameObject m in selectedGameObjects) { CreatePrefab(m, m.name); } AssetDatabase.Refresh(); } } void OpenPrefabFolder() { string path = EditorUtility.OpenFolderPanel("选择要导出的路径", "", ""); if (!path.Contains(Application.dataPath)) { Debug.LogError("导出路径应在当前工程目录下"); return; } if (path.Length != 0) { int firstindex = path.IndexOf("Assets"); PrefabPath = path.Substring(firstindex) + "/"; EditorUtility.FocusProjectWindow(); } } void OpenObjFolder() { string path = EditorUtility.OpenFolderPanel("选择要导出的路径", "", ""); if (!path.Contains(Application.dataPath)) { Debug.LogError("导出路径应在当前工程目录下"); return; } if (path.Length != 0) { int firstindex = path.IndexOf("Assets"); ObjPath = path.Substring(firstindex) + "/"; EditorUtility.FocusProjectWindow(); } } void CreateObj(GameObject go) { if (!Directory.Exists(ObjPath)) { Directory.CreateDirectory(ObjPath); } MeshFilter[] meshfilters = go.GetComponentsInChildren(); if (meshfilters.Length > 0) { for (int i = 0; i < meshfilters.Length; i++) { ObjExporter.MeshToFile(meshfilters[i], ObjPath + meshfilters[i].gameObject.name + ".obj"); } } } /// /// 此函数用来根据某物体创建指定名字的Prefab /// /// 选定的某物体 /// 物体名 /// void void CreatePrefab(GameObject go, string name) { //先创建一个空的预制物体 //预制物体保存在工程中路径,可以修改("Assets/" + name + ".prefab"); GameObject tempPrefab = PrefabUtility.SaveAsPrefabAsset(go, PrefabPath + name + ".prefab"); MeshFilter[] meshfilters = go.GetComponentsInChildren(); if (meshfilters.Length > 0) { MeshFilter[] prefabmeshfilters = tempPrefab.GetComponentsInChildren(); for (int i = 0; i < meshfilters.Length; i++) { Mesh m_mesh = AssetDatabase.LoadAssetAtPath(ObjPath + meshfilters[i].gameObject.name + ".obj"); prefabmeshfilters[i].sharedMesh = m_mesh; } } PrefabUtility.ConnectGameObjectToPrefab(go, tempPrefab); //返回创建后的预制物体 } void OnInspectorUpdate() { //这里开启窗口的重绘,不然窗口信息不会刷新 this.Repaint(); } void OnSelectionChange() { //当窗口出去开启状态,并且在Hierarchy视图中选择某游戏对象时调用 selectedGameObjects = Selection.gameObjects; } } public class ObjExporter { public static string MeshToString(MeshFilter mf) { Mesh m = mf.sharedMesh; // Material[] mats = mf.GetComponent().sharedMaterials; StringBuilder sb = new StringBuilder(); sb.Append("g ").Append(mf.name).Append("\n"); for (int i = 0; i < m.vertices.Length; i++) sb.Append(string.Format("v {0} {1} {2}\n", -m.vertices[i].x, m.vertices[i].y, m.vertices[i].z)); sb.Append("\n"); for (int i = 0; i < m.normals.Length; i++) sb.Append(string.Format("vn {0} {1} {2}\n", -m.normals[i].x, m.normals[i].y, m.normals[i].z)); sb.Append("\n"); for (int i = 0; i < m.uv.Length; i++) sb.Append(string.Format("vt {0} {1}\n", m.uv[i].x, m.uv[i].y)); for (int material = 0; material < m.subMeshCount; material++) { sb.Append("\n"); int[] triangles = m.GetTriangles(material); for (int i = 0; i < triangles.Length; i += 3) { //Because we inverted the x-component, we also needed to alter the triangle winding. sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n", triangles[i] + 1, triangles[i + 1] + 1, triangles[i + 2] + 1)); } } return sb.ToString(); } public static void MeshToFile(MeshFilter mf, string filename) { using (StreamWriter sw = new StreamWriter(filename)) { sw.Write(MeshToString(mf)); } } } }