Up until this point I’ve used the following methods:
…to load a sound file from the disk at runtime.
However, after a player filed a bug report, I’ve discovered that this method does not support '#'s in the file path. I imagine this is a side-effect of using a web request to load from the local disk, '#'s are not allowed in URLs.
Which begs the question: given that '#'s are valid characters within a file path (at least on Windows), what method should we use to load a sound file at runtime to ensure that all paths can be successfully loaded?
I’m happy using File.ReadAllBytes() to read from the disk - no probs. But then I’m not sure how to decode the byte[ ] to an audioClip with Ogg Vorbis decoding.
Is there a way to manually set the result of the UnityWebRequest to the byte array, and then still use the DownloadHandlerAudioClip.GetContent(webRequest) to convert to the audioClip?
Hoping someone has already solved this one and can point me in the right direction. Thanks very much in advance.
You may be correct, have you tried removing the # from the URL? You may need to URL escape the character otherwise. What is the URL and the error message?
‘#’ is a special character in the URL (Fragment). If you want to read files with ‘#’ in path, the ‘#’ has to be escaped. A single path item can be escaped via UnityWebRequest.EscapeURL, you can also try using System.Uri class, UWR does accept it as well.
So for anybody else encountering this issue, the full code looks something like:
IEnumerator GetAudioClipFromLocalDisk(string filePath)
{
// Escape special characters so we don't get an HTML error when we send the request
filePath = UnityWebRequest.EscapeURL(filePath);
using (UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip("file:///"+filePath, AudioType.OGGVORBIS))
{
yield return www.SendWebRequest();
if (www.result == UnityWebRequest.Result.ConnectionError)
{
Debug.Log(www.error);
}
else
{
AudioClip myClip = DownloadHandlerAudioClip.GetContent(www);
}
}
}
Just be aware that this will also escape other characters, so for example:
“D:/” becomes “D%3a%2f”
The web request understands all the escaped characters but if you do a string.Contains(“/”) on the escaped string it would return false. So just be careful if you continue to do things with the file name after escaping it, or maybe don’t do that.
I am encountering an issue with the GetAudioClip function when the file path includes spaces. This issue occurs on Linux and Mac, but not on Windows. I have attempted to use UnityWebRequest.EscapeURL as a solution, but it does not work with GetAudioClip. My current workaround is to replace spaces with “%20” in the file path.
Unfortunately, System.Uri in raw doesn’t work on Linux (and probably on Mac) with spaces too. I’ve already tested it in my example. Here is my code for loading an AudioClip from disk using a path like this: Application.streamingAssetsPath + “/Movie/” + movieID + “.ogg”:
In my case (user report) for Steam Deck, the default Application.streamingAssetsPath includes spaces.
using (UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip(new System.Uri("file:///" + path), AudioType.OGGVORBIS))
I also try Uri.EscapeUri and it works for both:
using (UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip(new System.Uri(Uri.EscapeUri("file:///" + path)), AudioType.OGGVORBIS))
or
using (UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip(Uri.EscapeUri("file:///" + path), AudioType.OGGVORBIS))
PS: UnityWebRequest.EscapeURL, System.Uri.EscapeDataString do not work in case with file:///
This is not correct.
One thing is that file: followed by 3 slashes is only correct on Windows, UNIX-like OSes already have a slash at the start of absolute path, so the URI will not point to the file.
The actual problem is that you don’t need to provide the file protocol, just pass file path to Uri constructor, it should handle it fine.