Files
Fishing2/Assets/Scripts/Editor/MeshAssetObjExporter.cs
2025-07-26 20:12:34 +08:00

79 lines
2.2 KiB
C#

using UnityEngine;
using UnityEditor;
using System.IO;
using System.Text;
public class MeshAssetObjExporter
{
[MenuItem("Assets/Export Mesh (.asset) to OBJ", true)]
static bool ValidateExport()
{
return Selection.activeObject is Mesh;
}
[MenuItem("Assets/Export Mesh (.asset) to OBJ")]
static void ExportMeshAssetToObj()
{
Mesh mesh = Selection.activeObject as Mesh;
if (mesh == null)
{
Debug.LogWarning("Please select a Mesh .asset file in the Project window.");
return;
}
string path = EditorUtility.SaveFilePanel("Export OBJ", "", mesh.name + ".obj", "obj");
if (string.IsNullOrEmpty(path)) return;
ExportMeshToObj(mesh, path);
Debug.Log("Mesh exported to: " + path);
}
static Vector3 ConvertToBlender(Vector3 v)
{
// Unity坐标 (X, Y, Z) → Blender坐标 (X, Z, -Y)
return new Vector3(v.x, v.z, -v.y);
}
static void ExportMeshToObj(Mesh mesh, string path)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("# Exported from Unity MeshAssetObjExporter");
sb.AppendLine("g " + mesh.name);
// 顶点
foreach (Vector3 v in mesh.vertices)
{
Vector3 vBlender = ConvertToBlender(v);
sb.AppendFormat("v {0} {1} {2}\n", vBlender.x, vBlender.y, vBlender.z);
}
// 法线
foreach (Vector3 n in mesh.normals)
{
Vector3 nBlender = ConvertToBlender(n);
sb.AppendFormat("vn {0} {1} {2}\n", nBlender.x, nBlender.y, nBlender.z);
}
// UV
foreach (Vector2 uv in mesh.uv)
{
sb.AppendFormat("vt {0} {1}\n", uv.x, uv.y);
}
// 面
for (int i = 0; i < mesh.subMeshCount; i++)
{
int[] tris = mesh.GetTriangles(i);
for (int j = 0; j < tris.Length; j += 3)
{
int a = tris[j] + 1;
int b = tris[j + 1] + 1;
int c = tris[j + 2] + 1;
sb.AppendFormat("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\n", a, b, c);
}
}
File.WriteAllText(path, sb.ToString());
}
}