Search Unity

Using UWP API in Standalone Build

Discussion in 'Scripting' started by plmx, Mar 4, 2018.

  1. plmx

    plmx

    Joined:
    Sep 10, 2015
    Posts:
    308
    Hi,

    I have the need to access the Windows 10 UWP Bluetooth API (Windows.Devices.*) for accessing Bluetooth LE (GATT) in a non-UWP (Standalone) Unity build. The reason for not using the UWP target in Unity is that we are creating software for SteamVR as well as the Oculus platform, not only WMR, and both are not supported on UWP.

    The code will only ever run on Windows 10, so there is no issue with the functionality not being there "physically", it is "merely" a question of access. Now, I understand that Unity uses a custom .NET implementation which makes this a non-straightforward problem, and I have not managed to get it to work so far. What is the preferred way of doing this? So far, I've tried:

    a) Directly using the UWP API by adding references in the Visual Studio project (as described here). That way Visual Studio allows me to use the API, but Unity reports "error CS0246: The type or namespace name `Windows' could not be found. Are you missing an assembly reference?"; and the same with changing Unity player settings to "Experimental .NET 4.6". As far as I read the Unity docs, I would have to physically copy the relevant libraries into the project asset folder for this to work? Unfortunately I have to real clue which DLLs/other files are required by the BT API and whether this would even work if I did.

    b) Creating a DLL for accessing the UWP API and then using that in Unity. I first tried to create a .NET 3.5-targetted Windows Universal Class Library in Visual Studio and copying the resulting DLL to the Asset folder. Unfortunately, Unity refuses to make the contents of said DLL available ("Assets/BTTest.cs(4,7): error CS0246: The type or namespace name `BTDotNet35ClassLibrary' could not be found. Are you missing an assembly reference?". Then I switched Unity to .NET 4.6 Experimental, which changed the error message to "Assets/BTTest.cs(11,32): error CS0012: The type `System.Object' is defined in an assembly that is not referenced. Consider adding a reference to assembly `System.Runtime, Version=4.0.20.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'"

    Soooo... does anyone have any further ideas, or is using UWP in this way impossible/not recommended? I'd rather not go IPC for this ;-)

    Thanks,

    Philip
     
  2. OlafZ

    OlafZ

    Joined:
    Aug 3, 2016
    Posts:
    17
    We have the same question/request. We would like to use the Adaptive Streaming API that WinRT offers, but Unity refuses to allow Windows Runtime APIs to be accessed on the Standalone Windows platform.

    The only solution we were thinking of is to create a native library that calls the UWP API. But that seems unnecessarily convoluted, especially since Unity already has support for Windows Runtime for Unity UWP apps. It would be great if we did not have to resort to native/managed interop to work around a limitation of Unity to access the managed UWP APIs directly.

    It should also be noted that Microsoft officially supports calling many of the UWP APIs directly from desktop apps, as these resources indicate:
    UWP APIs callable from a classic desktop app
    Calling Windows 10 APIs From a Desktop Application
     
  3. plmx

    plmx

    Joined:
    Sep 10, 2015
    Posts:
    308
    After spending countless hours on this, I can say that while using UWP DLLs from .NET might be possible in certain select cases, the whole thing takes on another level of complexity when turning to Unity's mono implementation, and in particular from the "non-experimental" Mono 3.5 version, which is so outdated regarding current APIs that there are no easy adaptations possible.

    However: The other thing is that UWP is Microsoft's newest platform, and many of their APIs, including the Bluetooth LE/GATT API we were looking at, are still rather simple, and amazingly buggy (and in fact, there are large differences between the .NET4.6 and the UWP API, even in terms of method names). UWP is also extremely boxed in; you can't open process pipes and not even a server TCP port for local communication.

    These two things together don't mesh well. Suffice it to say, we did not find a solution regarding the integration of UWP APIs on Unity. I can only advise: "Don't".

    So, what did we do? In our specific case (Bluetooth), we switched to a commercial LE/GATT implementation. The company we are now using has both C++ and C# versions of their libs and they, in fact, were likewise unable to get the C# version to run on Unity (despite the fact that it was based on 3.5; some marshaling issues); however, it WAS possible to use a C++ DLL wrapper for the C++ version along with a Unity-based C# facade, which does work nicely. For us, this concludes things.

    @OlafZ if you manage to find a native lib workaround via dynamic libraries, this might shed new light on the issue.

    HTH.

    Philip
     
    JVLVince likes this.
  4. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Pipes not, but you should be able to use TCP and some other kinds of sockets. Make sure you've got the capabilities checked and try to use the implementations defined in Windows.Networking.Sockets for UWP builds. Or try to use the usual System.Net namespace and run an IL2CPP build.
    If IL2CPP does not work or is simply not an option, you might just use an adapter pattern and resolve the platform specific implementations at start up. We've done this for multiple things in order to be able to support an older huge code base for editor/standalone, while using the new APIs during development for the HoloLens (UWP) and this works quite well.
     
  5. plmx

    plmx

    Joined:
    Sep 10, 2015
    Posts:
    308
    Suddoha, thanks for chiming in! I seem to have some different information regarding the sockets:

    Microsoft themselves state that is impossible to use IPC via network sockets due to network isolation ("Network communications using an IP loopback address cannot normally be used for interprocess communication between a Universal Windows Platform (UWP) app and a different process (a different UWP app or a desktop app) because this is restricted by network isolation."). See here and here. In my tests, using the UWP as a client does work, but whether this is an error in the API or by design is not known, so I'm not relying on it.

    Of course we'd encapsulate the platform-specific implementations once we get it working, but getting Unity to access UWP API from a non-IL2CPP build has just not worked out as I stated above; it is not even possible to start the game due to assembly recognition issues. I suspect this is due to mismatches of the .NET versions and thus inaccessible, newer API - we are trying to use a NEWER managed library in an OLDER implementation, not the other way around as you have. I guess the only option is to encapsulate everything in non-managed code (as we are doing now).

    If you have managed to access UWP-only API in Unity-Mono-3.5 I'd of course be happy to hear how :)

    Philip
     
    Last edited: Mar 20, 2018
    Suddoha likes this.
  6. Deleted User

    Deleted User

    Guest

    @plmx, we're experiencing the same issue having to use UWP bluetooth api in a standalone desktop build. Could you please let me know the name of the plugin/alternative implementation you ended up using? Thanks!
     
  7. plmx

    plmx

    Joined:
    Sep 10, 2015
    Posts:
    308
  8. holo-krzysztof

    holo-krzysztof

    Joined:
    Apr 5, 2017
    Posts:
    77
    If anyone from Unity comes here, it'd be really nice to be able to opt-in to Windows Runtime support for a Windows Standalone build. Consider following scenario:

    - Due to our dependencies, we're constrained to running on Windows 10 14393 at minimum. We want to support Win32 as well as UWP.
    - We're creating a native plugin and need it to be callable from C#.
    - That means creating an ugly C wrapper in between C# and C++ code which is a manual and error-prone process

    Now, if it were possible to just use a Windows Runtime Component, everything would be much easier. The interop layer that's already within Mono would take care of marshaling and all the ugly COM stuff underneath and we could have a nice API callable from both languages.
     
  9. erzshalom

    erzshalom

    Joined:
    Jun 13, 2018
    Posts:
    3
    @plmx - Thanks for sharing we have the same problem.

    i will appreciate if you can reproduce the step towards your solution ?
    1. you downloaded their C++ trail version cause c# wasn't working in Unity ? then you wrote a wrapper for Unity ?

    2. regarding your request from them - "Upon request they sent me a simple C++/C# wrapper for me to extend.." what was the extend for? can you elaborate?

    Thanks!
     
  10. plmx

    plmx

    Joined:
    Sep 10, 2015
    Posts:
    308
    Hi @erzshalom,

    I first tried the C# version of their framework, and couldn't get it to work in Unity due to .NET version mismatches and Mono/.NET issues. I then asked them for help, and they couldn't get it to work either, so they wrote a C++-to-C# "bridge" or "wrapper" (consisting of a C++ VS project, and some C# code for Unity) for me, which works with the C++ version of their framework, and which I could then successfully use with their C++ framework version in Unity. I then bought their C++ framework version.

    The bridge/wrapper they sent me is a "demo" in the sense that it does not translate all functionality of their framework into Unity; it was just some code for them to show it works and for me to get started, that's why I wrote "for me to extend", I had to add all other required functionality of their C++ framework to the bridge myself. You can obviously also write the entire bridge yourself using only their C++ framework version. However, I am not very knowledgeable in C++ low level stuff, so it was very helpful for me to get started to have at least a working example of some functionality.

    I would suggest you write them and explain about using Unity. I also suggested to them to sell this as an asset on the Unity store, but I don't think they got around to doing that yet.

    Philip
     
  11. xmedeko

    xmedeko

    Joined:
    Jun 6, 2018
    Posts:
    23
    We have the same problem. We have Windows standalone .NET using Bluetooth LE UWP API and want to port it to Unity standalone app. Also has fount this thread https://forum.unity.com/threads/bluetooth-low-energy-on-windows-under-unity.509387/

    The Unity NET 4.6 backend is stable now in Unity 2018. Is it possible to use Windows Runtime API from standalone Unity Windows App now? Or are there any plans to use in Unity 2019? May someone form Unity ( @Tautvydas-Zilys ) answer that? Thanks.

    @plmx Bluetooth Framework advertise to support Unity NET 4.6, https://forum.btframework.com/index.php/topic,3532.msg8983.html#msg8983
    Do you use it? Is it the same solution you have described or something new? Thanks.
     
  12. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    We didn't explicitly work on this.

    It definitely won't work on Mono scripting backend because it doesn't understand Windows Runtime.

    I don't know if it works in IL2CPP - IL2CPP in general supports Windows Runtime, however, we don't automatically reference Windows.winmd and friends from your scripts when targeting Windows Standalone. Perhaps try copying the winmd file into the project and see if it works? I honestly haven't tried it.
     
  13. adabru

    adabru

    Joined:
    Jan 19, 2016
    Posts:
    3