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
相关产品推荐
相关产品推荐

