This is a very rough post to collect some thoughts about trying to write .NET libraries that work inside of the Unity Editor and in UWP projects for Mixed Reality. Apply a large pinch of salt, it’s still a “work in progress” at this point so I’ll add to it/update it as I progress but I wanted somewhere to write things down but feel free to feedback…
I’ve been trying to write a library which works in the Unity Editor and also at runtime in a UWP app built from the Unity Editor.
Generally, I’ve been following the excellent guides;
Porting Guide (the section titled ‘Writing Plugins’)
Universal Windows Platform: Plugins on .NET Scripting Backend
and the essence has been to produce 2 libraries by targeting .NET Framework 3.51 and the Universal Windows Platform (14393 in my case).
I’ve been doing this by making use of shared projects in Visual Studio such that I have 3 projects inside of Visual Studio;
with all of the code being shared between the two “head” projects, one of which compiles for .NET Framework 3.51 whereas the other compiles for UWP 14393.
Within that code, I then make use of #if WINDOWS_UWP to conditionally work on pieces of code that do/don’t rely on the UWP and I’ve made sure that the publicly visible API surface of the library is the same in both cases.
Initially, I thought that this would largely involve staying away from types like Task<T> which don’t exist in .NET Framework 3.51 but I found that it can be more nuanced than that.
While the projects above don’t look like it, they both build out a DLL with the same name (as per the guidance) and I have then installed those two DLLs into my Unity project as the documentation suggests so that the UWP one is in a WSA sub-folder and the .NET Framework one is in the Plugins folder;
and I configure the .NET Framework assembly to run only in the editor;
and I configure the UWP assembly to run only in the WSA Player and I set its “placeholder” to point to the .NET Framework 3.51 assembly;
This was all going rather well until I came to run my code in the Unity editor and at that point I found that I was having some trouble with the types that were being passed across the boundary in/out of my code.
Purely as an example, I was making use of IPAddress as a return type from a public function and it seemed “safe” in that it seems to come from namespace System.Net for both .NET Framework 3.51 and for UWP but when I came to build in Unity I hit an error message telling me that Unity was looking for IPAddress in the System assembly whereas for UWP it looks to live in System.Net.Primitives.
I’m not sure if there’s some “type forwarding” style smart away around this but it stopped me building and I had to replace the use of the IPAddress type with the String type in my public interface and, similarly, get rid of types like AddressFamily as well which I was also passing out of my assembly.
That wasn’t too bad as it bit me at Unity build time but then I started to hit some runtime fun as well.
For instance, I found that I had a piece of code inside of my DLL which did something similar to the fragment below.
Given;
class Base { } class Derived : Base { }
and some code;
var factories = new List<Func<Base>>(); factories.Add(() => new Derived());
then I would find that this would blow up on my at runtime with an ArrayTypeMismatchException in the Editor which I’m guessing is related to;
and which forced me to change the way in which I was writing code inside of my class library. Note – I wasn’t actually using Func<> in my example, that’s just to shorten the code here.
It wasn’t a big change but it took quite a while to figure out why it was happening and I suspect I might hit more examples as I go along and so I’ll update this post as/when that happens…
Pingback: Experiments with Shared Holograms and Azure Blob Storage/UDP Multicasting (Part 2) – Mike Taulty