Serialization in WinForms, Deserialization in Unity

To make a long story short, I’m using the WinForms technology as my game editor. What I’m hoping to accomplish is to send my serialized game objects from Winforms to Unity.

I’ll use a fake example to be less complex as possible.

Step one, I create a class/structure in my WinForms project. I’ll also copy that one in my Unity folders. The class looks like this:

using System;
    using System.Runtime.Serialization;
    using System.Runtime.Serialization.Formatters.Binary;
    
    [Serializable()]
    class My_Data_Structure : ISerializable
    {
    	public int x;
    	public int y;
    	public string name;
    	
    	public My_Data_Structure()
    	{
    		x = 0;
    		y = 0;
    		name = "This is a Unity Test, Ta-Da!";
    	}
    	
    	public My_Data_Structure(SerializationInfo info, StreamingContext ctxt)
    	{
    		x = (int)info.GetValue("x", typeof(int));
    		y = (int)info.GetValue("y", typeof(int));
    		name = (String)info.GetValue("name", typeof(string));
    	}
    		
    	public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
    	{
    		info.AddValue("x", x);
    		info.AddValue("y", y);
    		info.AddValue("name", name);
    	}
    	
    	
    }

Step Two, a bit later inside my Winforms project, I instantiate an object and serialize it:

My_Data_Structure my_unity_test = new My_Data_Structure();
    my_unity_test.x = 100;
    my_unity_test.y = 200;
    			
    string full_filename = "Unity_Test" + ".csdata";
    Stream stream = File.Open(full_filename, FileMode.Create);
    BinaryFormatter bFormatter = new BinaryFormatter();
    bFormatter.Serialize(stream, my_unity_test);

From this point, I have no problem to deserialize it from within my WinForms project.

Step Four, Now I try to deserialize it from Unity. First, I copy/paste the Unity_Test.csdata inside my Unity local folder > Assets\Resources\Game_Csdata\Unity_Test.Csdata

I also make sure to import My_Data_Structure class inside my Unity project.

Then I try to get my serialized object from this script inside Unity:

Stream stream = File.Open("Assets\\Resources\\Game_Csdata\\Unity_Test.Csdata", FileMode.Open);
    BinaryFormatter bFormatter = new BinaryFormatter();
    My_Unity_Test my_unity_test = new My_Unity_Test();
    my_unity_test = (My_Unity_Test)bFormatter.Deserialize(stream);

Sadly I get FileNotFoundException: Could not load file or assembly ‘NGINE, Version=1.0.4944.4274, Culture=neutral, PublicKeyToken=null’ or one of its dependencies. The system cannot find the file specified." [the error pursue many more lines]

Anyone have an idea what to do? I’m a bit lost. I’ve spent a bunch of hours trying to figure out the best way I should serialize between WinForms and Unity without success.

Thank you in advance for your help!

Did you tried to load any other file from this location? FileNotFoundException - seems like file path is incorrect.

Hey Patico! Thanks for replying! Actually, I thought the same thing too, but I think it would fail there initially:

Stream stream = File.Open("Assets\\Resources\\Game_Csdata\\Unity_Test.Csdata", FileMode.Open);

File.Open succeed to open the serialized file.

I wonder if it’s not a compatibility issue with Unity, but my serialized file use .Net, everything that Unity should understand.

I think it is not possible to use File.Open in Unity 3D. Take a look at the TextAsset class Unity - Scripting API: TextAsset ant its propety bytes - Unity - Scripting API: TextAsset.bytes.

It’s interesting but how do we assign a file to TextAsset? I haven’t found how on this part of the documentation.

EDIT: I figured out, just need to drag and drop the file in the project.

Oops. Sorry, my fault, forget about 1 more link
See here Unity - Manual: Text assets and everything will be clear)))

TextAsset bindata= Resources.Load("Game_Csdata\\Unity_Test") as TextAsset;

UPD: You should put file into the Resources folder and change the extension to .bytes

It is possible, I used File.Open to read in a JSON file for a tile map (from Tiled) importer.

You can also follow the discussion here: Serialization from WinForms to Unity - Questions & Answers - Unity Discussions

Maybe we can solve this issue all together? I really need to know it can work :smile:

Well, one possible issue that I can think of is the fact that you are serializing the object within .Net and then deserializing in Mono. The main issue arises from the use of BinaryFormatter, which is not advised for cross-platform serialization.

Take a look at this StackOverflow answer for more info.

Thanks a lot XGundam05, I will investigate the issue about BinaryFormatter.

As long as I can find a clean way to serialize in WinForms and deserialize in Unity I will be very happy :slight_smile:

There’s always XML serialization, DataContractSerializer will do private variables/fields I believe. Granted, the files will be larger than with Binary serialization, but XML is platform agnostic.

@the_scholar have you found any solution to this? I’m running into this with an error saying “Failed to read past end of file” and it’s occuring on the same line as you. I suspect that it’s related some how.

Frankly, I think that’s the issue if I read it write.

Pasting a .cs into Unity does not make it the same class. Don’t forget that a class is also define by its assembly. When you serialize stuff, it basically say “This data is for this AssemblyQualifiedName”. http://msdn.microsoft.com/en-us/library/system.type.assemblyqualifiedname(v=vs.110).aspx

When you compile the .CS inside Unity, it get a totally different AssemblyQualifedName. The class may sport the same name, but the assembly is not. Therefore, the serialize is unable to retrieve the proper type.

For this kind of stuff, you would need to compile your class into a .DLL, and use the same DLL from your WinForm app and from your Unity project. That way, the AssemblyQualifiedName wouldn’t change.

However, I would have to ask… Why the hell do you want to generate data from a WinForms application?