300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > Unity场景中导出模型插件

Unity场景中导出模型插件

时间:2021-07-01 04:47:25

相关推荐

Unity场景中导出模型插件

我们在开发中,可能会遇到,需要在unity中拼场景,然后到处模型给美术优化的情况,这种情况下,就需要在Unity中导出模型的操作了

思路

实际这个功能的设计思路也很简单,根据在场景中选择的对象,获取它的mesh数据,然后把数据重新生成文件就好了

实现

1.网格数据类

这个类是用来获取网格各个部分的数据信息的

保存网格名称

private void SaveMeshName(MeshFilter meshFilter, StringBuilder data){data.Append("g ").Append(meshFilter.name).Append("\n");}

保存顶点数据

private static void SaveVertices(MeshFilter meshFilter, StringBuilder data){foreach (Vector3 ver in meshFilter.sharedMesh.vertices){Vector3 worldPos = meshFilter.transform.TransformPoint(ver);//因为坐标系的区别,x分量需要反转data.Append(string.Format("v {0} {1} {2}\n", -worldPos.x, worldPos.y, worldPos.z));}data.Append("\n");}

保存法线数据

private void SaveNormals(MeshFilter meshFilter, StringBuilder data){foreach (Vector3 normal in meshFilter.sharedMesh.normals){Vector3 directionWorld = meshFilter.transform.TransformDirection(normal);data.Append(string.Format("vn {0} {1} {2}\n", -directionWorld.x, directionWorld.y, directionWorld.z));}data.Append("\n");}

保存uv数据

private void SaveUVs(MeshFilter meshFilter, StringBuilder data){foreach (Vector3 uv in meshFilter.sharedMesh.uv){data.Append(string.Format("vt {0} {1}\n", uv.x, uv.y));}}

保存材质数据

private void SaveMaterails(MeshFilter meshFilter, StringBuilder data, Dictionary<string, MaterialData> materialDic){Mesh mesh = meshFilter.sharedMesh;Material[] materialArray = meshFilter.GetComponent<Renderer>().sharedMaterials;string materialName = "";for (int materialIndex = 0; materialIndex < mesh.subMeshCount; materialIndex++){materialName = materialArray[materialIndex].name;data.Append("\n");data.Append("usemtl ").Append(materialName).Append("\n");data.Append("usemap ").Append(materialName).Append("\n");//筛选同名材质,不重复添加if (!materialDic.ContainsKey(materialName)){MaterialData materialData = new MaterialData();materialData.Name = materialName;materialData.TextureName =materialArray[materialIndex].mainTexture ?AssetDatabase.GetAssetPath(materialArray[materialIndex].mainTexture) : null;materialDic[materialData.Name] = materialData;}//保存三角形数据int[] triangles = mesh.GetTriangles(materialIndex);for (int i = 0; i < triangles.Length; i += 3){data.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n",triangles[i] + 1 + _vertexOffset, triangles[i + 1] + 1 + _normalOffset,triangles[i + 2] + 1 + _uvOffset));}}_vertexOffset += mesh.vertices.Length;_normalOffset += mesh.normals.Length;_uvOffset += mesh.uv.Length;}

2.导出文件部分功能

导出多个模型为一个文件

public static void ExportObjsToOne(MeshFilter[] mf, string folder, string filename){MeshData data = new MeshData();using (StreamWriter sw = new StreamWriter(folder + "/" + filename + ".obj")){sw.Write("mtllib ./" + filename + ".mtl\n");foreach (MeshFilter mesh in mf){data.SaveData(mesh);sw.Write(data.ToString());}}ExportMaterials(data.GetMaterialDic(), folder, filename);}

导出单个模型为一个文件

public static void ExportObjToOne(MeshFilter mf, string folder, string filename){MeshData data = new MeshData();data.SaveData(mf);using (StreamWriter sw = new StreamWriter(folder + "/" + filename + ".obj")){sw.Write("mtllib ./" + filename + ".mtl\n");sw.Write(data.ToString());}ExportMaterials(data.GetMaterialDic(), folder, filename);}

保存材质

private static void ExportMaterials(Dictionary<string, MaterialData> materialList, string folder, string filename){using (StreamWriter sw = new StreamWriter(folder + "/" + filename + ".mtl")){foreach (KeyValuePair<string, MaterialData> kvp in materialList){sw.Write("\n");sw.Write("newmtl {0}\n", kvp.Key);sw.Write("Ka 0.6 0.6 0.6\n");sw.Write("Kd 0.6 0.6 0.6\n");sw.Write("Ks 0.9 0.9 0.9\n");sw.Write("d 1.0\n");sw.Write("Ns 0.0\n");sw.Write("illum 2\n");if (kvp.Value.TextureName != null){string destinationFile = kvp.Value.TextureName;int stripIndex = destinationFile.LastIndexOf('/');if (stripIndex >= 0)destinationFile = destinationFile.Substring(stripIndex + 1).Trim();string relativeFile = destinationFile;destinationFile = folder + "/" + destinationFile;try{File.Copy(kvp.Value.TextureName, destinationFile);}catch{}sw.Write("map_Kd {0}", relativeFile);}sw.Write("\n\n\n");}}}

2.编辑器菜单部分

这个模式会将父物体和子物体的模型分别导出为单独的模型文件

[MenuItem("BlueToolKit/导出模型/将选中模型分别导出(子物体会拆分导出)")]private static void ExportAllChild(){if (!ExportFile.CreateExportFolder())return;Transform[] selection = Selection.GetTransforms(SelectionMode.Editable | SelectionMode.ExcludePrefab);if (selection.Length == 0){EditorUtility.DisplayDialog("未选中模型", "请选中一个或多个模型", "关闭");return;}int exportCount = 0;for (int i = 0; i < selection.Length; i++){Component[] meshfilter = selection[i].GetComponentsInChildren(typeof(MeshFilter));for (int m = 0; m < meshfilter.Length; m++){exportCount++;ExportFile.ExportObjToOne((MeshFilter)meshfilter[m], ExportFile.EXPORT_FOLDER, selection[i].name + "_" + i + "_" + m);}}if (exportCount > 0)EditorUtility.DisplayDialog("导出成功", "成功导出 " + exportCount + " 个模型", "关闭");elseEditorUtility.DisplayDialog("导出失败", "导出模型必须含有Mesh Filter组件", "关闭");}

这个模式会将所有选中的模型导出为一个模型文件

[MenuItem("BlueToolKit/导出模型/将选中模型导出成一个obj文件")]private static void ExportToSingleObj(){if (!ExportFile.CreateExportFolder())return;Transform[] selection = Selection.GetTransforms(SelectionMode.Editable | SelectionMode.ExcludePrefab);if (selection.Length == 0){EditorUtility.DisplayDialog("未选中模型", "请选中一个或多个模型", "关闭");return;}int exportCount = 0;ArrayList mfList = new ArrayList();for (int i = 0; i < selection.Length; i++){Component[] meshfilter = selection[i].GetComponentsInChildren(typeof(MeshFilter));for (int m = 0; m < meshfilter.Length; m++){exportCount++;mfList.Add(meshfilter[m]);}}if (exportCount > 0){MeshFilter[] mf = new MeshFilter[mfList.Count];for (int i = 0; i < mfList.Count; i++){mf[i] = (MeshFilter)mfList[i];}string filename = SceneManager.GetActiveScene().name + "_" + exportCount;int stripIndex = filename.LastIndexOf('/'); //FIXME: Should be Path.PathSeparatorif (stripIndex >= 0)filename = filename.Substring(stripIndex + 1).Trim();ExportFile.ExportObjsToOne(mf, ExportFile.EXPORT_FOLDER, filename);EditorUtility.DisplayDialog("导出成功", "导出模型名称:" + filename, "关闭");}elseEditorUtility.DisplayDialog("导出失败", "导出模型必须含有Mesh Filter组件", "关闭");}

这个模式会将选中物体和子物体的模型导出为一个文件,选择几个模型就到处几个

[MenuItem("BlueToolKit/导出模型/将选中模型分别导出(子物体不拆分导出)")]private static void ExportParent(){if (!ExportFile.CreateExportFolder())return;Transform[] selection = Selection.GetTransforms(SelectionMode.Editable | SelectionMode.ExcludePrefab);if (selection.Length == 0){EditorUtility.DisplayDialog("未选中模型", "请选中一个或多个模型", "关闭");return;}int exportCount = 0;for (int i = 0; i < selection.Length; i++){Component[] meshfilter = selection[i].GetComponentsInChildren(typeof(MeshFilter));MeshFilter[] mf = new MeshFilter[meshfilter.Length];for (int m = 0; m < meshfilter.Length; m++){mf[m] = (MeshFilter)meshfilter[m];}exportCount++;ExportFile.ExportObjsToOne(mf, ExportFile.EXPORT_FOLDER, selection[i].name + "_" + i);}if (exportCount > 0){EditorUtility.DisplayDialog("导出成功", "成功导出 " + exportCount + " 个模型", "关闭");}elseEditorUtility.DisplayDialog("导出失败", "导出模型必须含有Mesh Filter组件", "关闭");}

这个小插件在有需求的时候,还是蛮好用的,希望对大家有帮助,完整代码可以到我的工具集里找到

工具收录于我自己写的工具集,内部还有我写的几个小插件,我会慢慢更新,欢迎关注

工具集地址:/BlueMonk1107/BlueToolkit

我会在我的公众号上推送新的博文,也可以帮大家解答问题

微信公众号 Andy and Unity 搜索名称或扫描二维码

希望我们能共同成长,共同进步

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。