Unity中如何优雅处理损坏的外部WAV文件?
问题背景
加载格式正确的WAV文件时代码运行正常,但加载用户提交的无效WAV(比如0长度文本文件改后缀)时,调用DownloadHandlerAudioClip.GetContent会触发FMOD错误导致崩溃,且该错误无法通过try/catch捕获:
Error: Cannot create FMOD::Sound instance for clip "" (FMOD error: Unsupported file or audio format. )
UnityEngine.Networking.DownloadHandlerAudioClip:GetContent (UnityEngine.Networking.UnityWebRequest)
XMLFrobnicator/d__12:MoveNext () (at Assets/Scripts/XMLFrobnicator.cs:197)
UnityEngine.SetupCoroutine:InvokeMoveNext (System.Collections.IEnumerator,intptr)
原代码如下:
using (UnityWebRequest uwr = UnityWebRequestMultimedia.GetAudioClip(fileName, AudioType.WAV)) { yield return uwr.SendWebRequest(); if(uwr.result != UnityWebRequest.Result.Success) { Debug.Log(uwr.error); yield break; } else { try { app.levelMusic = DownloadHandlerAudioClip.GetContent(uwr); } catch(System.Exception e) { Debug.Log(e); yield break; } } }
解决方案
1. 提前验证WAV文件的头部格式
最可靠的方式是在调用GetContent前,先验证下载到的字节流是否符合WAV文件的基本结构,避免触发FMOD的底层错误。
WAV文件有固定的头部标识,我们可以检查以下关键特征:
- 文件字节长度至少大于44字节(标准WAV头部的最小长度)
- 前4字节为ASCII码"RIFF"
- 第8-11字节为ASCII码"WAVE"
- 第12-15字节为ASCII码"fmt "
验证函数示例:
private bool IsValidWavHeader(byte[] data) { // 标准WAV头部至少44字节 if (data == null || data.Length < 44) return false; // 检查RIFF标识 string riff = System.Text.Encoding.ASCII.GetString(data, 0, 4); if (riff != "RIFF") return false; // 检查WAVE标识 string wave = System.Text.Encoding.ASCII.GetString(data, 8, 4); if (wave != "WAVE") return false; // 检查fmt块标识 string fmt = System.Text.Encoding.ASCII.GetString(data, 12, 4); if (fmt != "fmt ") return false; return true; }
修改原代码,加入验证步骤:
using (UnityWebRequest uwr = UnityWebRequestMultimedia.GetAudioClip(fileName, AudioType.WAV)) { yield return uwr.SendWebRequest(); if(uwr.result != UnityWebRequest.Result.Success) { Debug.Log(uwr.error); yield break; } // 获取下载的字节数据 byte[] wavData = uwr.downloadHandler.data; if (!IsValidWavHeader(wavData)) { Debug.LogError("无效的WAV文件格式"); yield break; } // 验证通过后再加载音频剪辑 try { app.levelMusic = DownloadHandlerAudioClip.GetContent(uwr); } catch(System.Exception e) { Debug.Log(e); yield break; } }
2. 替代方案:手动解析WAV数据创建AudioClip
如果需要更精细的控制,可以跳过DownloadHandlerAudioClip.GetContent,手动解析WAV字节流,用AudioClip.Create创建音频剪辑,这样能完全控制错误处理流程,避免触发FMOD的底层崩溃。不过这种方式需要处理WAV的采样率、通道数、位深度等参数,实现起来更复杂。
关于启动外部进程的建议
Unity确实支持通过System.Diagnostics.Process启动外部进程,但这种方式会增加项目复杂度,跨平台兼容性差,且没必要——提前验证WAV头部已经能覆盖绝大多数无效文件场景,是更优的选择。
内容的提问来源于stack exchange,提问作者Cassandra Gelvin

