我正在为 Windows 制作 Unity 桌面应用程序,在我的应用程序中,文件类型 glb 和 gltf 的 3D 模型在运行时从磁盘加载到场景中。这些在 Unity 编辑器中运行良好,但当我构建它时,模型无法加载。
我使用 Siccity.GLTFUtility 加载这些文件。
这是与该问题相关的 Player.log 错误(就我而言,整个日志文件中没有其他错误):
ArgumentNullException: Value cannot be null.
Parameter name: shader
at (wrapper managed-to-native) UnityEngine.Material.CreateWithShader(UnityEngine.Material,UnityEngine.Shader)
at UnityEngine.Material..ctor (UnityEngine.Shader shader) [0x00008] in <ed4b14358c3a426aacd38939413c3d3b>:0
at Siccity.GLTFUtility.GLTFMaterial+PbrMetalRoughness+<CreateMaterial>d__5.MoveNext () [0x0006a] in <a234369d3f4e4b83afe3dc4030317985>:0
at Siccity.GLTFUtility.GLTFMaterial+<CreateMaterial>d__14.MoveNext () [0x000b9] in <a234369d3f4e4b83afe3dc4030317985>:0
at Siccity.GLTFUtility.GLTFMaterial+ImportTask+<OnCoroutine>d__4.MoveNext () [0x00114] in <a234369d3f4e4b83afe3dc4030317985>:0
at Siccity.GLTFUtility.Importer+ImportTask`1[TReturn].RunSynchronously () [0x0001b] in <a234369d3f4e4b83afe3dc4030317985>:0
at Siccity.GLTFUtility.Importer.LoadInternal (Siccity.GLTFUtility.GLTFObject gltfObject, System.String filepath, System.Byte[] bytefile, System.Int64 binChunkStart, Siccity.GLTFUtility.ImportSettings importSettings, UnityEngine.AnimationClip[]& animations) [0x000ab] in <a234369d3f4e4b83afe3dc4030317985>:0
at Siccity.GLTFUtility.Importer.ImportGLB (System.String filepath, Siccity.GLTFUtility.ImportSettings importSettings, UnityEngine.AnimationClip[]& animations) [0x00012] in <a234369d3f4e4b83afe3dc4030317985>:0
at Siccity.GLTFUtility.Importer.LoadFromFile (System.String filepath, Siccity.GLTFUtility.ImportSettings importSettings, UnityEngine.AnimationClip[]& animations, Siccity.GLTFUtility.Format format) [0x00033] in <a234369d3f4e4b83afe3dc4030317985>:0
at Siccity.GLTFUtility.Importer.LoadFromFile (System.String filepath, Siccity.GLTFUtility.Format format) [0x00006] in <a234369d3f4e4b83afe3dc4030317985>:0
at MultiModelLoader+<DownloadAndSaveFile>d__44.MoveNext () [0x00159] in <d1494a091caf4b75869a10c4f73429a5>:0
at UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) [0x00026] in <ed4b14358c3a426aacd38939413c3d3b>:0
UnityEngine.MonoBehaviour:StartCoroutineManaged2(MonoBehaviour, IEnumerator)
UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
<LoadFiles>d__42:MoveNext()
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
UnityEngine.MonoBehaviour:StartCoroutineManaged2(MonoBehaviour, IEnumerator)
UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
MultiModelLoader:PaginateItems(String[])
MultiModelLoader:ReadData()
<Start>d__37:MoveNext()
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
以下是将 3D 模型加载到场景中的 C# 代码的主要部分:
IEnumerator DownloadAndSaveFile(string fileId, Vector3 position)
{
string extension = items[fileId].ModelFileExtension;
string fileName = fileId + "_model." + extension;
string folderPath = modelPath + category + "/";
string filePath = folderPath + fileName;
// Check if the file already exists
if (File.Exists(filePath))
{
CustomDebug("File " + fileName + " already exists in " + folderPath);
}
else
{
// Download the file from Firebase Storage and save it to local storage
UnityWebRequest www = UnityWebRequest.Get(storageUrl + "models%2F" + fileName + "?alt=media");
www.downloadHandler = new DownloadHandlerFile(filePath);
yield return www.SendWebRequest();
if (www.result != UnityWebRequest.Result.Success)
{
Debug.Log(www.error);
yield break;
}
CustomDebug("File " + fileName + " downloaded and saved to " + folderPath);
}
// Load the GLTF file using the GLTFUtility library
gltfObject = Importer.LoadFromFile(filePath);
// Set the object's name to the file name (without extension)
gltfObject.name = Path.GetFileNameWithoutExtension(fileId);
// Set the parent object
gltfObject.transform.SetParent(parentObject.transform);
// Calculate the bounding box of the model before scaling
Bounds preBounds = gltfObject.GetComponentInChildren<MeshRenderer>().bounds;
// Calculate the scale factor needed to fit the bounding box within a desired size
float desiredSize = 2f; // desired size in world units
float scaleFactor = desiredSize / preBounds.size.magnitude;
// Apply the scale factor to the model
gltfObject.transform.localScale *= scaleFactor;
// Add a BoxCollider to the object
gltfObject.AddComponent<BoxCollider>();
// Set the layer of the object to Realtime for realtime lighting to affect it
int layerIndex = LayerMask.NameToLayer("Realtime");
// Since some models contain child objects, it's required to set all objects to that layer to receive lighting
SetLayerRecursively(gltfObject, layerIndex);
gltfObject.layer = layerIndex;
// Position the object in the scene as desired
gltfObject.transform.position = position;
// Add gravity to the objects and let it place itself on the surface
gltfObject.AddComponent<Rigidbody>();
gltfObject.GetComponent<Rigidbody>().isKinematic = false;
gltfObject.GetComponent<Rigidbody>().useGravity = true;
}
由于使用 StartCoroutine 函数调用上述函数,我还认为使用多线程方法做同样的事情可能会起作用。但我尝试了一下,即使在编辑器中也失败了。以下是 Siccity 在他的 github 页面中的建议:
// Single thread
using Siccity.GLTFUtility;
void ImportGLTF(string filepath) {
GameObject result = Importer.LoadFromFile(filepath);
}
// Multithreaded
using Siccity.GLTFUtility;
void ImportGLTFAsync(string filepath) {
Importer.ImportGLTFAsync(filepath, new ImportSettings(), OnFinishAsync);
}
void OnFinishAsync(GameObject result, AnimationClip[] animations) {
Debug.Log("Finished importing " + result.name);
}
正如相关 gltf 加载器的 github 页面所述,我将每个单独的着色器添加到 Always Included Shaders 但它仍然不起作用。
除此之外,我还尝试随机启用一些选项,看看其中是否有效。
这是我的第一个 Unity 项目,我正在为期末考试做这个项目。我决定在这里问这个问题,因为我已经没有时间和选择了。任何有关如何解决此问题的帮助/建议将非常感激。
谢谢!
现在回答你可能有点晚了,但是如果你的项目使用了urp渲染管线,你必须在图形设置中添加GLTFUtility相应的着色器,而不仅仅是内置的!