Open Source WebSocket client

Hi there. Long time listener, first time caller. I’m Mike Schweitzer, a generalist engineer in the game industry.

I made an open source WebSocket client for Unity that works on web and “non-web” platforms without any additional dll downloads or installs.

This is a runtime client only (MonoBehaviour), so not for use in Editor code.

https://github.com/mikerochip/unity-websocket

Details are on the github page, but here is a copy of the features:

  • Easy to use

  • Doesn’t force you to use async/await: use event listeners, coroutines, or polling

  • Doesn’t force you to use #if for WebGL: no platform-specific code required to use it

  • WebSocketConnection is just a MonoBehaviour

  • Public API prevents you from corrupting an active connection

  • Reusable: connect, disconnect, change URL, connect again, etc

  • Flexible config

  • URL is the only required config

  • Sane defaults

  • Optionally set subprotocols, max send, and max receive bytes

  • Wide platform support

  • No external install requirements or dependencies

  • string is treated as text and byte[ ] as binary (some servers care)

  • Customizable ping-pong support for servers that enforce idle timeouts

  • Web uses a JavaScript lib WebSocket.jslib, and includes support for WebAssembly.Table from Unity 2023.2+

  • Other platforms use the built-in System.Net.WebSockets

This is why I did it, maybe you’ve had a similar story and would consider using this package for similar reasons:

  • In the earlier Unity days, I manually downloaded and vendored WebSocket4Net from NuGet

  • Never feels great to manually download things from NuGet

  • The NuGetForUnity package has several issues that make me not a fan of using it in modern Unity projects

  • More recently tried using NativeWebSocket, but encountered DX issues (developer experience)

  • Requires async/await

  • Requires conditional compilation for Web

  • After wanting to make my own fixes / modifications, I found the source difficult to navigate

  • I put a lot of value on ease-of-use and ergonomics when building workflows and tools

No shade to NativeWebSocket, my work is based on that. Very grateful for that. I just wanted to fix the issues and the fixes I wanted to make were way too extensive to open a PR that might not get merged.

Thanks!

5 Likes

Very cool! Thanks for sharing, Mike.

I’m curious about this assertion you make:

More recently tried using NativeWebSocket, but encountered DX issues… requires conditional compilation for Web

What do you mean by conditional compilation? Aren’t both libraries conditionally compiled in the sense that they use a jslib on Web vs System.Net.WebSocket on other platforms, as determined by #UNITY_WEBGL conditions?

hey curious why not extend for editor as well

Sorry I’m not sure how I missed a notification for this reply. The implementations both use conditional compilation, yes, but NativeWebSocket requires the user of the package to use conditional compilation and async as well, so IMO it leaks its internal implementation and forces consumers into its patterns; that’s the part I had an issue with.

You can see that in its sample code here:

  async void Start()
  {
    websocket = new WebSocket("ws://localhost:3000");
...

  void Update()
  {
    #if !UNITY_WEBGL || UNITY_EDITOR
      websocket.DispatchMessageQueue();
    #endif
  }

My package does not require users to use async nor conditional compilation. Hope that makes sense!

Mostly because I’m not sure what value an editor version of this would provide over using System.Net.WebSocket.ClientWebSocket directly. Most of the value of my package in my eyes is

  • Make runtime websocket client usage feel idiomatic to Unity (components, coroutines, update method, etc), where you don’t have to worry about lifecycle issues that you do with async
  • Not require you to bring in external dependencies outside of a UPM reference (e.g. you don’t have to vendor websocket-sharp or websocket4net etc)
  • Not require conditional compilation depending on target platform

In editor code you can use System.Net.WebSocket.ClientWebSocket directly without the above issues. I guess I could make an EditorWebSocketConnection to help manage async lifecycle issues since that’s a super sharp edge in editor code. I’m not sure what other value it would provide though? Thoughts?

I’d consider it if I saw more utility.