You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity代码绑定模型内嵌纹理后材质纹理为空问题求助

问题描述
  • 需求:将GLB模型导入Unity,通过代码为新创建的材质绑定模型内嵌纹理;手动操作可正常完成,但代码实现后,材质虽能保存到资源文件夹,纹理却未绑定。
  • 核心代码片段:
public UnityEngine.Texture Texture;
public override Material PopulateMaterial()
{
    var material = new Material(Shader.Find("Skybox/Panoramic"));
    foreach (var asset in AssetDatabase.LoadAllAssetsAtPath("Assets/huh.glb"))
    {
        Debug.Log(asset);
    }
    Debug.Log(Texture);
    Debug.Log(material.mainTexture);
    material.SetColor("_Tint", Color.green);
    material.SetTexture("_MainTex", Texture);
    Debug.Log(material.mainTexture);
    return material;
}
  • 调试现象:日志显示纹理存在,材质主纹理设置前为null,设置后读取显示已绑定引用,但编辑器中查看材质时纹理仍为null。
  • 尝试过的无效操作:
    • 调用AssetDatabase.SaveAssets()和AssetDatabase.Refresh(),因处于导入阶段收到错误提示:Calls to "AssetDatabase.SaveAssets" are restricted during asset importing、Calls to "AssetDatabase.Refresh" are restricted during asset importing
    • 手动克隆纹理使用,仍因导入未完成导致问题
    • 尝试AssetDatabase.LoadAsset、AssetDatabase.ImportAsset的多种变体,无效果
  • 使用框架:KhronosGroup的UnityGLTF
解决方案

方案1:导入完成后回调处理

通过AssetPostprocessor监听GLB导入完成事件,此时纹理已完全导入AssetDatabase,再为材质设置纹理并保存:

using UnityEditor;
using UnityEngine;

public class GLBPostProcessor : AssetPostprocessor
{
    static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
    {
        foreach (string path in importedAssets)
        {
            if (!path.EndsWith(".glb")) continue;
            
            // 加载GLB关联的所有资产,定位目标纹理
            Object[] allAssets = AssetDatabase.LoadAllAssetsAtPath(path);
            Texture targetTexture = null;
            foreach (Object asset in allAssets)
            {
                if (asset is Texture tex)
                {
                    targetTexture = tex;
                    break; // 根据实际需求匹配目标纹理
                }
            }

            if (targetTexture == null) continue;
            
            // 定位导入后生成的材质文件
            string materialPath = path.Replace(".glb", ".mat");
            Material material = AssetDatabase.LoadAssetAtPath<Material>(materialPath);
            if (material == null) continue;
            
            // 设置纹理并保存
            material.SetTexture("_MainTex", targetTexture);
            material.SetColor("_Tint", Color.green);
            EditorUtility.SetDirty(material);
            AssetDatabase.SaveAssets();
        }
    }
}

方案2:修改UnityGLTF材质生成逻辑

在PopulateMaterial方法中,确保使用已被AssetDatabase识别的纹理资产,并标记材质为脏对象,确保后续序列化时保留纹理引用:

public override Material PopulateMaterial()
{
    var material = new Material(Shader.Find("Skybox/Panoramic"));
    material.SetColor("_Tint", Color.green);
    
    // 验证纹理为已导入资产,再绑定
    if (Texture != null && AssetDatabase.Contains(Texture))
    {
        material.SetTexture("_MainTex", Texture);
        EditorUtility.SetDirty(material);
    }
    
    return material;
}

注:若UnityGLTF框架自动处理材质保存,此修改可确保纹理引用被正确序列化;若框架未处理,仍需结合方案1的导入后回调完成保存。

关键注意事项

  • 导入阶段禁止调用AssetDatabase.SaveAssets()和AssetDatabase.Refresh(),必须等待导入流程完全结束后再执行资产保存操作
  • 绑定的纹理必须是已被AssetDatabase索引的资产(可通过AssetDatabase.Contains()验证),临时纹理对象无法被持久化保存

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 09:53:11