3
\$\begingroup\$

Is there any way to implement websocket server, which I can run inside Unity3d standalone linux instance? I gonna connect to it directly from webpage (pure javascript, not Unity3d WebGL). I've tried to look for existing websockets libraries for C#, but the reason they does not fit because Unity3d can execute only Mono libraries with .NET 3.5 (.NET 4.6 in newest Unity3d 2017.1 release).

I have HttpListener server running fine, however for Websockets it needs lots of specific logic. Who knows any solution for this?

\$\endgroup\$
1
3
\$\begingroup\$

Websocket sharp: https://github.com/sta/websocket-sharp

It has a unity version which I've used as part of a cross-platform library and on a couple of local multiplayer games, and worked well. I have not tried using the server part of it though - only the client.

That said are you sure you want to have a unity app be the server? It might be more trouble than it's worth to make it discoverable on anything but a local network.

\$\endgroup\$
6
  • \$\begingroup\$ Thank you for your answer. Actually I've used the same library to implement my own Websockets server inside Unity3d. Just required some magic, but it works awesome. \$\endgroup\$ – Epsiloncool Feb 20 '18 at 22:08
  • \$\begingroup\$ @Epsiloncool hi when I try running a simple demo on the webGL build I get the error exception thrown: RuntimeError: memory access out of bounds,RuntimeError: memory access out of bounds in the JavaScript console and it won't even start? Has this happened to you ever? I'm using unity 2018.3.2 \$\endgroup\$ – bluejayke Jan 24 '19 at 6:34
  • \$\begingroup\$ @bluejayke Nah, sorry, I didn't try this with 2018.3.2. My version was 2017.1. \$\endgroup\$ – Epsiloncool Jan 24 '19 at 12:14
  • \$\begingroup\$ BTW I just found github.com/jirihybek/unity-websocket-webgl and it works perfect with the newest version of unity, even the free version in the webGL player, for you and anyone else out there wondering :) \$\endgroup\$ – bluejayke Jan 24 '19 at 22:31
  • \$\begingroup\$ With this repo, I'm getting errors with .NET 3.5 \$\endgroup\$ – Derk Jan Speelman Aug 16 '19 at 13:49
9
\$\begingroup\$

System.Net.WebSockets seems to be completely built-in to .Net and freely available in Unity.

Here's a full Websockets client for Unity for example:

using System;
using System.Text;
using System.Threading;
using System.Net.WebSockets;
using UnityEngine;

public class Comms: MonoBehaviour {
    Uri u = new Uri("ws://blah blah.us-west-1.compute.amazonaws.com:3333");
    ClientWebSocket cws = null;
    ArraySegment<byte> buf = new ArraySegment<byte>(new byte[1024]);

    void Start() { Connect(); }

    async void Connect() {
        cws = new ClientWebSocket();
        try {
            await cws.ConnectAsync(u, CancellationToken.None);
            if (cws.State == WebSocketState.Open) Debug.Log("connected");
            SayHello();
            GetStuff();
        }
        catch (Exception e) { Debug.Log("woe " + e.Message); }
    }

    async void SayHello() {
        ArraySegment<byte> b = new ArraySegment<byte>(Encoding.UTF8.GetBytes("hello"));
        await cws.SendAsync(b, WebSocketMessageType.Text, true, CancellationToken.None);
    }

    async void GetStuff() {
        WebSocketReceiveResult r = await cws.ReceiveAsync(buf, CancellationToken.None);
        Debug.Log("Got: " + Encoding.UTF8.GetString(buf.Array, 0, r.Count));
        GetStuff();
    }
}

.

One side issue ...

(Note - For anyone using that sample code, don't forget Unity has no threading. Using Debug.Log is just a trick for that demo.)

The three "async" calls in the example happen on some other thread. Just as in Unity whenever you (say) start some calculation thread or use a plugin. When you get information "back" on those other threads, of course, you absolutely cannot access Unity again. (IE, you can't access any of the actual game objects, their component scripts, or the frame loop in any way in Unity). What you do is just "leave the information somewhere" for Unity to find. This is a basic of threading in Unity. (As explained at great length HERE for example.) Please note that in the example code above, I cheaply use "Debug.Log" (which you can use from any thread) as pseudocode.

Even more important, don't use my code above! :O

While my code is not wrong, it is not really complete. And there is a huge amount of work to do to really use WS from scratch.

The only current library is: https://github.com/Marfusios/websocket-client

We changed a very large project from "my" raw .Net code, to that library. (Alternately I would have had to basically .. rewrite that whole library!)

And here's what you have to do in Unity! You must use a ConcurrentQueue.

It is completely meaningless to process messages "instantly" in Unity: it is frame based!

Every arriving message: put it in a queue, and process them once each frame:

{Note that threading is irrelevant here. It makes no difference, at all, whether your processing that is getting the messages is on the "main" thread, another thread, many threads, or it is being handled by a quantum computer! Each message has to be queued in the frame system.}

someLibrary_aMessageHasArrived
    {
        incoming_messages.Enqueue( the message text );
    };

and ... this must of course be in a MonoBehavior ...

ConcurrentQueue<string> incoming_messages = new ConcurrentQueue<string>();
void Update()
{
    if (incoming_messages.TryDequeue(out var message))
    {
        Handle(message); .. your code for handling a message
    }
}

So that's what you do with real time messages to a Unity app. (Or any frame-based engine.)

\$\endgroup\$
14
  • \$\begingroup\$ I remember looking into that a while back but it was not an option since Unity used an ancient version of .NET that didn't include the WebSockets library. now with access to 4.6 that's no longer a problem and this is a pretty good option. It is a little bit lower level than the STA-Websockets but that could be a good thing depending on your needs. \$\endgroup\$ – Mattia Mar 28 '19 at 14:27
  • \$\begingroup\$ how are you @Mattia . Right: indeed for client use (I mean, your unity app is a WS client) I can't see any reason you'd use anything else; it couldn't be simpler. So that's good news. I'm afraid, I have never tried having a WS server inside a Unity app, so I can't comment on that! :) Cheers! \$\endgroup\$ – Fattie Mar 28 '19 at 14:29
  • \$\begingroup\$ This is a bit off topic but I thought Unity was single threaded? How do those asyncs work? Is there an exception for Tasks? Did they make things thread safe and I didn't notice. \$\endgroup\$ – Mattia Mar 28 '19 at 17:42
  • 1
    \$\begingroup\$ BUT WAIT! Like you, we avoided using libraries. (The "sharp" one, is in fact, pretty much dead now / doesn't work.) Pls, read the new part of my answer ! Depending on your needs, you may like us realistically need to use a library. (If so, this is the only working library ATM github.com/Marfusios/websocket-client ) \$\endgroup\$ – Fattie Oct 7 '20 at 19:03
  • 1
    \$\begingroup\$ @LachoTomov it would seem to me if it DOES work for you, that's good! I encountered problems with disconnections and so on .. overall we had top move to a library. It's a topuh business; I do not like using libraries myself, but, that's what we had to do in this case. Hope it helps in some way, sorry I don't have a "definitive" answer! \$\endgroup\$ – Fattie Oct 8 '20 at 10:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.