我经常要在Unity中生成一些网格,但是这些网格需要交给美工修改,所以又要将网格输出为模型。于是就有了下面的代码:
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
/// <summary>
/// 将“一个”选中的对象输出为obj格式
/// </summary>
public class EditorObjExporter : ScriptableObject
{
private static int vertexOffset = 0;
private static int normalOffset = 0;
private static int uvOffset = 0;
private static string targetFolder = "Assets/ExportedObj";//文件路径,创建后需要打开路径才能看到刷新的模型
//核心代码,将网格转为能被obj读取的数据
private static string MeshToString(MeshFilter mf, List<string> meshList)
{
Mesh m = mf.sharedMesh;
StringBuilder sb = new StringBuilder ();
sb.Append ("g").Append (mf.name).Append ("\n");
foreach (Vector3 lv in m.vertices) {
Vector3 wv = mf.transform.TransformPoint (lv);
sb.Append (string.Format ("v {0} {1} {2} \n", -wv.x, wv.y, wv.z));
}
sb.Append ("\n");
foreach (Vector3 lv in m.normals) {
Vector3 wv = mf.transform.TransformDirection (lv);
sb.Append (string.Format ("vn {0} {1} {2} \n", -wv.x, wv.y, wv.z));
}
sb.Append ("\n");
foreach (Vector3 v in m.uv) {
sb.Append (string.Format ("vt {0} {1} \n", v.x, v.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) {
sb.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 += m.vertices.Length;
normalOffset += m.normals.Length;
uvOffset += m.uv.Length;
return sb.ToString ();
}
private static void MeshesToFile(MeshFilter[] mf, string folder, string filename)
{
vertexOffset = 0;
normalOffset = 0;
uvOffset = 0;
List<string> meshList = new List<string> ();
using(StreamWriter sw = new StreamWriter (folder + "/" + filename + ".obj")){//创建一个obj文件
for (int i = 0; i < mf.Length; i++) {
sw.Write (MeshToString (mf [i], meshList));//往obj文件中写入数据,即生成模型
}
}
}
//创建文件夹
private static bool CreateTargetFolder()
{
try {
System.IO.Directory.CreateDirectory (targetFolder);//已经创建文件夹时不会再创建
} catch {
return false;
}
return true;
}
[MenuItem("Custom/Export OBJ")]
static void ExportOBJ()
{
if (!CreateTargetFolder ())
return;
Transform[] selection = Selection.GetTransforms (SelectionMode.Editable | SelectionMode.ExcludePrefab);
if (selection== null) {
EditorUtility.DisplayDialog ("未选中", "请选择模型!", "确定");
return;
}
int exportedObjects = 0;
for (int i = 0; i < selection.Length; i++) {
Component[] meshfilter = selection [i].GetComponentsInChildren<MeshFilter> ();
MeshFilter[] mf = new MeshFilter[meshfilter.Length];
for (int m = 0; m < meshfilter.Length; m++) {
exportedObjects++;
mf [m] = (MeshFilter)meshfilter [m];
}
MeshesToFile (mf, targetFolder, selection [i].name + "_" + i);
}
if (exportedObjects > 0) {
EditorUtility.DisplayDialog ("成功", "已输出!", "确定");
} else
EditorUtility.DisplayDialog ("失败", "未输出!", "确定");
}
}