UnifiedIO - Cross-platform IO for Unity

UnifiedIO is available on the Asset Store!

Keeping it brief: UnifiedIO is a library of methods that handle file and directory reading/writing in Application.persistentDataPath. It is “unified” because it does so consistently for all main platforms, including Windows Store Apps (Windows/Mac/Linux, Android, iOS, Windows Phone, Windows Store Apps, Blackberry).

It was developed coming from this old but updated question/answer about IO on Windows Store Apps. Check that link or the library’s documentation for details on the problem that UnifiedIO tries to solve.

The asset includes:

UnifiedIO.Directory class:

bool Exists(string path)
void Create(string path)
void Rename(string path, string newName)
void Move(string path, string destinationPath)
void Copy(string path, string destinationPath)
void MoveInside(string path, string destinationPath)
void CopyInside(string path, string destinationPath)
void Delete(string path)
void DeleteContents(string path)
string[ ] GetFiles(string path, string searchPattern, SearchOption searchOption)
string[ ] GetDirectories(string path, string searchPattern, SearchOption searchOption)

UnifiedIO.File class:

bool Exists(string path)
void CreateEmpty(string path)
void Rename(string path, string newName)
void Move(string path, string destinationPath)
void Copy(string path, string destinationPath)
void MoveInside(string path, string destinationPath)
void CopyInside(string path, string destinationPath)
void Delete(string path)
Stream GetReadStream(string path)
Stream GetWriteStream(string path)
Stream GetAppendStream(string path)
byte[ ] ReadBytes(string path, int position = 0, int nBytes = 0)
void WriteBytes(string path, byte[ ] content)
void WriteBytes(string path, byte[ ] content**,** int position)
void AppendBytes(string path, byte[ ] content)
string ReadText(string path)
void WriteText(string path, string content)
void AppendText(string path, string content)
IList ReadLines(string path)
void WriteLines(string path, IEnumerable content)
void AppendLines(string path, IEnumerable content)

Most of these methods are similar in signature to what you find in the System.IO namespace, but internally include different code for the various main platforms, so that, no matter which one you’re building for, you can read/write/copy/move/rename/delete/enumerate/etc your app’s files and folders in Application.persistentDataPath.

If you want code that just provides IO in Windows Store Apps, while keeping your existing code for other platforms, you can also use UnifiedIO. Simply use platform dependent compilation and call UnifiedIO methods inside #if NETFX_CORE sections. Both the documentation and the question/answer linked before contain more details on this.

Please check the above list of methods before buying, so you don’t feel cheated in any way. If you require a method that is not currently present, I will consider suggestions!

If you buy, leave a rating or review if you can (good or bad; developers need feedback!). :slight_smile:

Finally, all UnifiedIO methods were unit-tested, but bugs can slip in any software, so I also welcome any bug reports.

Thanks for checking it out! :slight_smile:

  • Daniel

Do you intend to add support to File.ReadAllBytes?

I need to make this code works:

  if (Splash2File.Contains("://"))
        {
            var www = new WWW(Splash2File);
            yield return www;
            if (www.texture)
            {
                Splash2 = Sprite.Create(www.texture, new Rect(0, 0, www.texture.width, www.texture.height),
                    new Vector2(0.5f, 0.5f), 1);
            }
        }
        else
        {
            var _tex = new Texture2D(2, 2);
            if (File.Exists(Splash2File))
            {
                _tex.LoadImage(File.ReadAllBytes(Splash2File));
                Splash2 = Sprite.Create(_tex, new Rect(0, 0, _tex.width, _tex.height),
                    new Vector2(0.5f, 0.5f), 1);
            }
        }

@sevensails

UnifiedIO already has that function, but it’s called “ReadBytes” instead. :slight_smile: The signature is:

byte[] ReadBytes(string path)

You should be able to use it with:

UnifiedIO.File.ReadBytes(Splash2File)

If any problem arises, post here. I might only be able to answer tomorrow, though!

  • Daniel

Hey Daniel,
I’m porting iOS apps to Windows Phone 8.

Currently my iOS apps read a text file, then parse it using TinyXmlReader.js
The apps use Unity Javascript. Will I be able to call the various UnifiedIO functions from my Unity js scripts?

Thanks!

I’ll be honest with you and say that I’ve never used Unity’s JavaScript (UnityScript). However, I also have no reason to believe that it won’t work (due to the way Unity compiles both C# and JS code to assemblies). :slight_smile:

You just have to place “UnifiedIO” (the whole folder) inside the “Plugins” or “Standard Assets” folder in your project. This is because calling C# code from UnityScript code requires the C# code to be compiled first, and the two folders I mentioned are compiled before the remaining ones (see this link for more details). I just tested this and it worked as expected in the the Editor, calling the library successfully from js code. It also compiled nicely in a WP8 build.

In your case, you seem to want to read the whole file and then parse it with another script. You should be able to do this by calling UnifiedIO.File.ReadText(“path/to/file/inside/persistentDataPath”), which returns a string with the entire file contents.

I hope this helps. :slight_smile: I’ll probably add a short section about calling UnifiedIO from UnityScript next time I update the documentation. Thanks!

  • Daniel

Thanks for the info Daniel. Just bought UnifiedIO as it sounds like it’s going to solve my problems.

Future apps I develop will be done with C# to avoid headaches, but Unity js was what I first learned on. Redoing everything to C# for older apps would be a colossal pain.

If I run into any problems, I’ll let you know.

You’re quite welcome, Mark. Yeah, life is too short to port whole projects to another language. :slight_smile: Based what I know of features and compile times, I don’t think you’ll regret the switch to C# in new projects.

Any problem and I’m here. Oh, and if you have the time after you try UnifiedIO, leave a rating or even a review on the Asset Store. Whatever you think it deserves! It helps a lot, and might also help other people decide if they want the package. :slight_smile:

Hi there. I just recently bought UnifiedIO to help me tackle porting my iOS/Android project to Windows Phone 8 and Windows Store.
Using UnifiedIO I got Unity to finally stop exploding with errors during the build process, however I’m getting errors instead now from Visual Studio pertaining to UnifiedIO.

Any ideas why this might be happening? I’ve tested UnifiedIO on my iOS/Android projects to make sure it’s setup correctly and everything seems to be in order there.

Hi! Nothing comes to my mind currently, except that it should be something particular to the WSA API. I would like to know more, namely what platform where you were running your project. Was it Windows Store Apps, version 8 or 8.1? On a simulator or real device?

Could you tell me what is contained in that AggregateException? Visual Studio’s debugger might help here, but you can also use something like the following:

try {
    // your code that calls UnifiedIO.Directory.Create(...)
} catch (AggregateException exception) {
    foreach (Exception e in exception.InnerExceptions) {
        MonoBehaviour.print(e.Message);    // or any other way you use to print information
    }
}

Furthermore, do you know if it happens only in Directory.Create? Do other methods have problems? Sorry for all the questions! :slight_smile:

If you can, contact me via e-mail for further discussion. I’m always afraid that the forums won’t notify me of new messages, or that they will notify me at weird times.

Due to my timezone, I’m about to go sleep now, so I apologize in advance if I can only get back to you tomorrow!

  • Daniel
1 Like

Thanks for the quick reply! I’ll send you an email shortly.

Debug.Log("Application.persistentDataPath exists: " + UnifiedIO.Directory.Exists(Application.persistentDataPath));
Application.persistentDataPath exists: False

Should this not be True?

I think there is a misunderstanding in your code. :slight_smile: You should never try to pass Application.persistentDataPath as an argument to UnifiedIO, because the library already operates in that folder and only there. All paths should be relative to persistentDataPath, like using UnifiedIO.Directory.Exists(“Users”) and not UnifiedIO.Directory.Exists(Application.persistentDataPath + “/Users”). If you use the second, it will try to concatenate persistentDataPath twice internally, and come out wrong. Please check the documentation pdf that comes with the package.

That said, persistentDataPath should exist at all times, as it is created and handled by Unity (unless something catastrophic occurs!). It even uses the folder for Cloud services caches and similar. Did you have problems where it did not exist? That would break a lot of stuff, and not only UnifiedIO.

I must say that I didn’t predict that users could try calling UnifiedIO.Directory.Exists(“/”) or UnifiedIO.Directory.Exists(“”), which would be the correct ways to do what you are trying in UnifiedIO style, so these calls probably won’t work correctly in WSA (i.e. they should return true but in WSA they probably return false). But again, you shouldn’t use them. Unity handles the existence of that folder. :slight_smile:

I hope I have helped!

  • Daniel

Yes, that helped - thank you for clarifying!

I’m using Unity 5.2.2f1 and I have been having this issue when I compile. Unified IO is not even linked with my code yet.
I think there was a change in System.IO to UnityEngine.Windows from Unity 5.2.1f1 to 5.2.2f1 that might be the source of the issue.

Reference Rewriter found some errors while running with command --target=“Temp\StagingArea\Assembly-CSharp.dll” --additionalreferences=“Temp\StagingArea\ARM”,“Temp\StagingArea\x86” --platform=“C:\Program Files (x86)\Windows Phone Kits\8.0\Windows MetaData\Windows.winmd” --support=“Temp\StagingArea\WinRTLegacy.dll” --supportpartialns=Unity.Partial --system=System --dbg=pdb --framework=“C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\WindowsPhone\v8.0”,“C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v8.0\Libraries”,“C:\Program Files\Unity\Editor\Data\PlaybackEngines\wp8support\Players\ARM\release” --alt=System.Net;System.Net.Sockets,System.Net;System.Xml.Serialization;System.ComponentModel,System.Windows;System.Threading,mscorlib.
Error: method System.Void System.IO.Directory::Move(System.String,System.String) doesn’t exist in target framework. It is referenced from Assembly-CSharp.dll at System.Void UnifiedIO.SystemIO.Directory::Rename(System.String,System.String).
Error: method System.IO.DirectoryInfo System.IO.DirectoryInfo::get_Parent() doesn’t exist in target framework. It is referenced from Assembly-CSharp.dll at System.Boolean UnifiedIO.SystemIO.Directory::areSameDirectory(System.String,System.String).
Error: method System.IO.DirectoryInfo System.IO.DirectoryInfo::get_Parent() doesn’t exist in target framework. It is referenced from Assembly-CSharp.dll at System.Boolean UnifiedIO.SystemIO.Directory::isSubdirectory(System.String,System.String).
Error: method System.IO.DirectoryInfo System.IO.DirectoryInfo::get_Parent() doesn’t exist in target framework. It is referenced from Assembly-CSharp.dll at System.Boolean UnifiedIO.SystemIO.Directory::isSubdirectory(System.String,System.String).
Error: method System.IO.DirectoryInfo System.IO.DirectoryInfo::get_Parent() doesn’t exist in target framework. It is referenced from Assembly-CSharp.dll at System.Boolean UnifiedIO.SystemIO.Directory::isSubdirectory(System.String,System.String).

UnityEngine.Debug:LogError(Object)
PostProcessWinRT:RunReferenceRewriter() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:556)
PostProcessWinRT:Process() (at C:/buildslave/unity/build/PlatformDependent/WinRT/SharedSources/CSharp/PostProcessWinRT.cs:118)
UnityEditor.BuildPlayerWindow:BuildPlayerAndRun()

Hi there, @arendhil .

I’m sorry to hear that you are having problems. :frowning: I appreciate the report, as I was not aware of this issue. First of all, you are building for Windows Phone 8.0, correct?

I have three versions of Unity 5 installed and I just tested this in WP8. It is indeed a change in Unity. I can confirm that the problem you report happens in 5.2.2f1, but also happens in 5.2.1f1. It does not happen in 5.0.0f4.

Somewhere between those releases, Unity started adding this message when building for WP8, which might be related:

“Support for Windows Phone 8.0 will be removed in Unity 5.3, please switch to Windows Phone 8.1”

Every build should now be done for the Windows Apps platform, which does not include WP8 (it does have Phone 8.1). However, I don’t know why the removal of support from future 5.3 would affect older versions, which still have the WP8 platform menu. Maybe some breaking changes were already introduced due to Windows 10, but they shouldn’t! I will update to Windows 10 soon, so I expect to see some of these changes… :roll_eyes:

Could you explain what you mean by “I think there was a change in System.IO to UnityEngine.Windows”? 5.2.1f1 still has the problem, so this might not be the issue, but I still want to know, in case it helps. :slight_smile:

Finally, have you by any chance contacted Unity support about this? I assume you came here first, so I will contact them to try to get some answers. If this is a breaking change that they introduced, you would have to either revert to a previous Unity version that supports WP8 or get a refund from me. If UnifiedIO does not do what it’s supposed to, I think it’s fair, even though it is likely a Unity change.

  • Daniel

@arendhil

I was able to ask in the forums about this issue and it is a confirmed Unity bug in version 5.2. I have tested the newest patch release, 5.2.3p1, and the release notes mention this:

“(745932) - Windows Phone 8.0: Fixed regression with System.IO classes.”

Indeed, I have downloaded and tested this version and the errors related to WP8 seem to be gone. Unfortunately, these patch versions might be the only versions in the 5.2 releases which don’t have this bug, since Unity 5.3 will remove support for WP8.

I have tried to go around the issue by creating a custom dll for WP8, as was suggested to me, but was still unsuccessful. I would appreciate it if you could tell me if this is an urgent matter to you, or if you are at all able to update to 5.2.3p1, which solves the issue.

  • Daniel

Hi,

I want to get this asset.
I need to save a screenshot to a local folder (on all platforms).
Other assets that do this work, but only for android or ios, never for windows store or OSx.

Is it possible to write a texture 2D from the application to local storage (for ALL platforms) with this asset?

Hi there!

In general, anything you can convert to a byte array, string or write directly into a stream can be written in a cross platform way using UnifiedIO. Fortunately, Unity provides the EncodeToPNG method for textures, which returns the texture as a byte array, which you can then pass to UnifiedIO.File.WriteBytes to create a PNG image file.

So you can do something like this test class I created:

using UnityEngine;
using System.Collections;

public class ScreenshotTest : MonoBehaviour
{
    void Update ()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            StartCoroutine(takeScreenshot());
        }
    }

    IEnumerator takeScreenshot()
    {
        yield return new WaitForEndOfFrame();

        var texture = new Texture2D (Screen.width, Screen.height, TextureFormat.RGB24, true);
        texture.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
        texture.Apply();

        byte[] bytes = texture.EncodeToPNG();
        UnifiedIO.File.WriteBytes("screenshot.png", bytes); // normally, System.IO.File.WriteAllBytes
    }
}

Use the spacebar to take a screenshot of the game. It should save it in your game’s persistentDataPath folder.

I hope this helps! :slight_smile:

  • Daniel

Thanks, I am going to buy your plugin and try!
I will let you know if it works :slight_smile:

Ok it seems to work(at least for WSA, going to check other platforms soon) :slight_smile:

I know this is not part of the plugin, but maybe you know this.
I want to open the written png (even better its folder) afterwards and I can’t get it to work (windows store application).
Application.OpenUrl doesnt work (even when setting “File://” in front of it).
Do you have any idea how to do this?