You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Unity中为导出的OBJ文件生成MTL材质文件的技术咨询

How to Generate MTL Files for OBJ Exports in Unity

Hey there! Let's get your OBJ exports linked to MTL material files instead of exporting standalone textures. Here's a step-by-step breakdown of modifying your existing code to achieve this:

1. Quick Background

The MTL file defines material properties (like texture references) that your OBJ will point to. Instead of exporting separate texture files, we'll configure the MTL to reference your existing texture assets directly—this keeps your export clean and aligned with standard OBJ/MTL workflows.

2. Updated ObjExporter Class

We'll add a method to generate MTL content, update the OBJ to reference the MTL, and adjust the export logic to save both files together. Here's the full modified code:

using System.IO;
using System.Text;
using UnityEngine;

public class ObjExporter {
    // Generate OBJ content with MTL reference
    public static string MeshToString(MeshFilter mf, string mtlFileName) {
        Mesh m = mf.mesh;
        Material[] mats = mf.GetComponent<Renderer>().sharedMaterials;
        StringBuilder sb = new StringBuilder();

        // Link OBJ to the corresponding MTL file
        sb.Append(string.Format("mtllib {0}\n", Path.GetFileName(mtlFileName)));
        sb.Append("g ").Append(mf.name).Append("\n");

        // Write vertex data
        foreach (Vector3 v in m.vertices) {
            sb.Append(string.Format("v {0} {1} {2}\n", v.x, v.y, v.z));
        }
        sb.Append("\n");

        // Write normal data
        foreach (Vector3 v in m.normals) {
            sb.Append(string.Format("vn {0} {1} {2}\n", v.x, v.y, v.z));
        }
        sb.Append("\n");

        // Write UV data (fixed to Vector2 since Unity UVs are 2D)
        foreach (Vector2 v in m.uv) {
            sb.Append(string.Format("vt {0} {1}\n", v.x, v.y));
        }

        // Write submesh and material references
        for (int material = 0; material < m.subMeshCount; material++) {
            sb.Append("\n");
            sb.Append("usemtl ").Append(mats[material].name).Append("\n");
            
            int[] triangles = m.GetTriangles(material);
            for (int i = 0; i < triangles.Length; i += 3) {
                sb.Append(string.Format("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\n", 
                    triangles[i] + 1, triangles[i + 1] + 1, triangles[i + 2] + 1));
            }
        }
        return sb.ToString();
    }

    // Generate MTL content for each material
    public static string MaterialToString(Material[] mats, string textureBasePath) {
        StringBuilder sb = new StringBuilder();

        foreach (Material mat in mats) {
            sb.Append(string.Format("\nnewmtl {0}\n", mat.name));
            // Default material properties (adjust these to match your in-game materials if needed)
            sb.Append("Ka 1.000 1.000 1.000\n"); // Ambient color
            sb.Append("Kd 1.000 1.000 1.000\n"); // Diffuse color
            sb.Append("Ks 0.000 0.000 0.000\n"); // Specular color
            sb.Append("Ns 0.000\n"); // Specular exponent
            sb.Append("d 1.000\n"); // Transparency (1 = opaque)

            // Link the material's main texture
            Texture mainTex = mat.mainTexture;
            if (mainTex != null) {
                // Use the texture's filename (ensure textures are in the same folder as OBJ/MTL, or adjust the path here)
                string textureFileName = mainTex.name + Path.GetExtension(mainTex.name);
                sb.Append(string.Format("map_Kd {0}\n", textureFileName));
            }
        }
        return sb.ToString();
    }

    // Export both OBJ and MTL files
    public static void MeshToFile(MeshFilter mf, string objFilename) {
        // MTL file will be saved in the same directory as the OBJ
        string mtlFilename = Path.ChangeExtension(objFilename, ".mtl");
        string textureBasePath = Path.GetDirectoryName(objFilename);

        // Write OBJ file
        using (StreamWriter sw = new StreamWriter(objFilename)) {
            sw.Write(MeshToString(mf, mtlFilename));
        }

        // Write MTL file
        Material[] mats = mf.GetComponent<Renderer>().sharedMaterials;
        using (StreamWriter sw = new StreamWriter(mtlFilename)) {
            sw.Write(MaterialToString(mats, textureBasePath));
        }

        Debug.Log($"Export complete! OBJ: {objFilename}, MTL: {mtlFilename}");
    }
}

3. Key Changes Explained

  • OBJ-MTL Link: Added mtllib {0} at the top of the OBJ to connect it to the generated MTL file.
  • MTL Texture References: The MaterialToString method creates material entries with map_Kd, which points directly to your existing texture files.
  • UV Fix: Updated UV handling to use Vector2 (Unity meshes store UVs as 2D values, your original code had a minor mismatch here).
  • Path Alignment: The MTL is saved in the same directory as the OBJ, and texture references use filenames—just make sure your texture files are placed in the same folder as the exported OBJ/MTL, or adjust the path logic to match your project structure.

4. How to Use

Call the updated MeshToFile method like you did before—now it will generate both files automatically:

ObjExporter.MeshToFile(GetComponent<MeshFilter>(), Application.dataPath + "/MyExportedModel.obj");

内容的提问来源于stack exchange,提问作者skgames

火山引擎 最新活动