Using SignalR.Client in Unity UWP apps

Jonas Hundertmark
medialesson
Published in
5 min readJan 2, 2023
Photo by Thomas Jensen on Unsplash

At this point, my fate seems to be building esoteric tech stacks on top of Unity, so let’s get to it:

SignalR is Microsoft’s homegrown solution for sending and recieving notifications to and from web servers. It’s a really powerful and easy-to-use tool for asynchronous communication within the .NET ecosystem. You basically just download the NuGet Package and build your implementation on top of it.

…If you’ve ever tried to add NuGet packages to your Unity project, that sentence has probably already triggered your fight-or-flight response, but we’ll get through it together. Additionally, we’ll be deploying to the Universal Windows Platform (UWP) for this demo, which makes things a bit more complicated. UWP is what powers things like Hololens 2-apps, so this demo could form the basis of a fairly lightweight networking solution for HL2 (Although I would still recommend dedicated networking frameworks like PUN for that).

1) Getting things ready

For this step, I would strongly suggest creating a new .NET Console application from an IDE of your choice (I‘ll be using VS2022, but use whatever you fancy). There’s a NuGet pagage manager plugin for Unity somewhere but I’ve had limited success with it (i.e. none). You can also try downloading all the required DLLs yourself from nuget.org, but that opens the door to a bunch of human error.

For Framework, choose the most recent version of .NET your Unity release supports. Current LTS releases go all the way up to 4.8. For releases older than 2020.3, .NET Framework 4.6.1 seems to work well. Double check your Unity Project Settings and the Unity docs. Also, while we’re here, make sure that your API Compatibility Level is set to “.NET Framework

In your newly created solution, select “Manage NuGet Packages…” and search for Microsoft.AspNetCore.SignalR.Client.

IMPORTANT: Install version 5.0.17 of this package, as all versions from 6.0.0 onwards require .NET 6, which Unity doesn’t support.

Visual Studio will download a bunch of packages (35 in total if you did everything correctly). The NuGet packages will be placed in your solution folder under /packages.

2) Configuring the Unity Project

If you haven’t already, create a folder called “Plugins” inside your Unity Assets folder. Then, from your /packages folder, drag and drop the following files from the /lib folders of the following packages. Usually, you want the “net461” version of the DLL, but I’ll provide the correct path for every file in italics.

  • Microsoft.AspNetCore.Connections.Abstractions.dll (net461)
  • Microsoft.AspNetCore.Http.Connections.Client.dll (net461)
  • Microsoft.AspNetCore.Http.Connections.Common.dll (net461)
  • Microsoft.AspNetCore.Http.Features.dll (net461)
  • Microsoft.AspNetCore.SignalR.Client.dll (net461)
  • Microsoft.AspNetCore.SignalR.Client.Core.dll (net461)
  • Microsoft.AspNetCore.SignalR.Common.dll (net461)
  • Microsoft.AspNetCore.SignalR.Protocols.Json.dll (net461)
  • Microsoft.Bcl.AsyncInterfaces.dll (net461)
  • Microsoft.Extensions.DependencyInjection.dll (net461)
  • Microsoft.Extensions.DependencyInjection.Abstractions.dll (net461)
  • Microsoft.Extensions.Logging.dll (net461)
  • Microsoft.Extensions.Logging.Abstractions.dll (net461)
  • Microsoft.Extensions.Options.dll (net461)
  • Microsoft.Extensions.Primitives.dll (net461)
  • System.Diagnostics.DiagnosticSource.dll (net46)
  • System.IO.Pipelines.dll (net461)
  • System.Runtime.CompilerServices.Unsafe.dll (net45)
  • System.Text.Encodings.Web.dll (net461)
  • System.Text.Json.dll (net461)
  • System.Threading.Channels.dll (net461)

You should get no script compilation errors once you added all the listed DLLs. If you do, double check whether you missed any files or if your API compatibility level is set to “.NET Standard 2.0/2.1

If you’re only deploying to Win Standalone, you can skip to step 3 at this point. For UWP, we still need to do a little bit more. Notice how we skipped a good third of the 35 packages NuGet added earlier? Unity still needs those on UWP. So we’ll need to reference them manually. Create a new text file in your /Assets folder and call it “csc.rsp

Open the file with a text editor of your choice and paste the following lines into it:

We can safely ignore the remaining DLLs. Now — finally — we can get to writing the actual implementation.

3) Implementing SignalR.Client into Unity

It’s usually a good idea to wrap SignalR endpoints into their own connector class. Don’t worry about the “Message” class in this example. You can freely extend or alter it, depending on your needs.

Now all you need to do is initialize your endpoint, connect some handler method to it and you’re good to go! This is how a (very simple) SignalR-Service MonoBehaviour could look like, just to give you some inspiration:

You could use this service to manage an arbitrary number of SignalR endpoints and handle events accordingly. Use SendAsync() to send a Message to the server and add a listener to NewMessageRecieved to listen to Messages coming from the server. If you want, you can call DontDestroyOnLoad() on this MonoBehaviour and turn it into a Singleton, but for the moment, let’s keep it at that. We still have a few more bases to cover. At this point. You can test out your project and send some Messages to your server. Everything should work fine.

4) Some additional considerations

First of all, you should think about adding a custom Retry Policy to your SignalRConnector class, as connections seem to be a little bit unstable depending on what version of SignalR.Server you are talking to. Retry Policies implement IRetryPolicy and can be added to your HubConnectionBuilder via .WithAutomaticReconnect() before you call .Build(). You can also just pass a TimeSpan as an argument, if you’re too lazy to write a custom implementation, or nothing at all if you’re happy with the default.

Server-Side problems are not the only way your connection can be cut off though, as Unity’s Application.Pause() can interfere with SignalR connections. This happens every time you return to the menu on HoloLens 2, so it’s important that you keep it in mind. You might wanna check the status of your SignalR HubConnections when you resume your Unity application (i.e. OnApplicationPause(false)).

5) Conclusion

I wouldn’t really call SignalR my first choice when it comes to networking solutions for Unity, but sometimes your hands are tied to a specific technology and you gotta make it work somehow. This tutorial is the result of a lot of trial-and-error and I’m happy I got it to work in the end. Most of the stuff I’ve found online has been incomplete, outdated or only usable on Win Standalone and I’ve been looking for a general way to get SignalR working on Unity on all platforms.

You could also use this tutorial to add any other NuGet package into Unity, though you may need to figure out which DLLs to add explicitly (as Plugins) and which ones to reference in your csc.rsp.

Hope you learned something!

--

--