UnityGLTF
UnityGLTF copied to clipboard
Import at runtime from local file with spaces in the path
Unless I'm misunderstanding something or having a moment of stupidity - UnityWebRequestLoader breaks because the relative path is url encoded (so spaces become %20) by GetFileFromUri but then the File.Exists check in LoadStreamAsync fails because it doesn't unencode the spaces
I looked at using FileLoader instead but there's no documentation and it has wildly different behaviour when running in the editor (even in play mode) so I'm not sure if this is the right direction.
- Should I be using UnityWebRequestLoader or FileLoader?
- Is FileLoader's execution path differences in the editor intentional? Why is it trying to use the AssetDatabase?
I'm not sure I can follow – can you provide reproduction steps (a file, a script, etc.) for what goes wrong? We're testing many different cases, including complex/non-typical paths, and they should all work. If something doesn't, it's a bug. Thanks!
The different loaders are partly legacy, partly because different scenarios have different requirements – e.g. in most cases UnityWebRequest is the right one at runtime, but in the editor we want to be able to defer to the AssetDatabase so that textures and buffers living next to a .gltf file can be resolved from there, and so on.
in most cases UnityWebRequest is the right one at runtime,
OK. That at least tells me that it's probably an issue at my end rather than me just misunderstanding what loader to use.
I'll dig a bit deeper. Closing this as it's most likely pebkac...
OK – let us know if run into further issues. I definitely don't want to rule out that we can improve things with the current loaders, or that there's still a case where we do it wrong.
So - after more testing, there's either a bug or some surprising behaviour that needs to be documented.
I have a file on disk with a space in the path. I am calling the importer thus:
GLTFSceneImporter gltf = new GLTFSceneImporter(localPath, options);
Now - the only choice I have at this stage is whether localPath should be urlencoded or not. Unfortunately the code inside UnityWebRequestLoader fails in both cases:
If I pass in a urlencoded path it gets double-escaped (The constructor code calls GetFileFromUri on the supplied path)
So I conclude that I must pass in an non-encoded path (i.e. spaces are still spaces and not %20)
If I do pass in a non-encoded path it goes via this code in VerifyDataLoader:
_options.DataLoader = new UnityWebRequestLoader(URIHelper.GetDirectoryName(_gltfFileName));
_gltfFileName = URIHelper.GetFileFromUri(new Uri(_gltfFileName));
Note that UnityWebRequestLoader is initialized with the unescaped directory path but _gltfFileName is set to the escaped filename because of code in GetFileFromUri.
Then we get to the following code in UnityWebRequestLoader:
var path = Path.Combine(dir, relativeFilePath).Replace("\\","/");
if (File.Exists(path)) path = "file://" + Path.GetFullPath(path);
var request = UnityWebRequest.Get(path);
var asyncOperation = request.SendWebRequest();
The "File.Exists" check fails because you're testing an encoded path against the file system. Therefore "file://" is not preprended UnityWebRequest
At this point you have a path like "c:\My folder\my%20filename.gltf"
This always results in a 404 from UnityWebRequest
The only thing that works is:
- Unescape the whole path to avoid double escaping
- Prepend file:/// yourself
This is an odd mix of requirements - which combined with complexities in my codebase - took me a fairly long time to figure out.
Hi again, and thanks for the summary – we can take a look if we can improve this!
The only thing that works is: Unescape the whole path to avoid double escaping Prepend file:/// yourself
My understanding is that this is exactly how UnityWebRequest is supposed to be used, with unescaped paths and with file:// prepended if what you want to request is actually a file (compared to the http: or https: protocols). Not saying that this is a great design though :) and also agree that other cases where we can figure out intent should just "gracefully work", ideally.