My multi-platform Unity project has experienced multiple major problems on UWP that turned out to be due to how local files are access from dataPath, or streamingAssetsPath.
The root issue was that the “System.IO.File/Directory” operations, which we’ve always used on other platforms, mostly work fine on this platform… until they don’t. (For us these issues cropped up at the worst possible time - after our app was in submission to Xbox, at which time we would discover that the app froze at startup due to File operations failing - since the directories used for a store-install had different permissions than those used in a sideloaded test. These issues repeatedly jeopardized our game’s Xbox submissions.) One example was that trying to read a text file using System.IO.StreamReader would fail, but only when installed on this file system and when the file size was 0 bytes.
My understanding is that this is all basically because System.IO.File/Directory API is a synchronous API but that UWP/WinRT only really supports async operations… and/or because the UWP platform compiles against a unique version of mono/.NET. It took me a while to find the guidance that UnityEngine.Windows.File operations are preferred on UWP.
The subtle bugs caused by using System.IO, which only crop up in certain situations, feels like… a trap. Even when I tried to switch all of our game’s file operations over to the UnityEngine.Windows.File API, I missed some places (e.g. I replaced all our usages of File.Exists() but failed to catch a usage of FileInfo.Exists()). The fact that our cross-platform team could easily add usages of the problematic endpoints and introduce the problem again on this platform without realizing it, is very worrying.
It seems like Unity should do one of the following
- Make System.IO operations on UWP not work - ie throw “InvalidOperation” errors - if you ever try to use them.
- Better yet, make System.IO operations unavailable at compile-time, or at least flagged with [Obsolete], when compiling code for UWP platform.
- Even better yet, just make the synchronous System.IO operations call the correct/reliable async operations on this platform (but block on them so that it still serves as a synchronous API to the code using these endpoints). (This would fix the current situation where all file operations need to be surrounded by #ifdef UNITY_WSA instances to use the other API.)
…And Unity should definitely make the pitfalls of not using the correct endpoints more obvious in documentation and porting guides, as these issues were not at all obvious and rarely mentioned in the docs. The most information I found about these issues were here:
- This detailed Unity Answers post, part of which may be irrelevant now since UWP .NET platform has been dropped: Handling the lack of System.IO classes in Windows Store Apps (Windows 8 Metro apps) - Questions & Answers - Unity Discussions
- This blog post: https://livierickson.com/blog/accessing-unity-streamingassets-in-universal-windows-apps/
Can a Unity rep explain why these operations fail, and why we’re allowed to use System.IO.File operations on this platform if they’re unreliable/unsafe? (Am I wrong in thinking that they just shouldn’t be used at all on this platform?) It would be nice to hear that Unity had a better long-term solution that didn’t require special-case file IO behavior for this platform.