UNET and Steamworks

I’m looking at adding multiplayer to an existing game using UNET as the API and Steam (via Steamworks) to matchmake / connect users.

As understand it, Unity’s matchmaking and user connection service will be a paid service. Am I correct in saying that I could use Steam (via Steamworks) to do this side for free while still using the UNET API to hook up all the data that needs moving around?

As you can imagine, I’m very new to networking principles so I’m still quite hazy on how this all fits together, even after reading all the blogs and info on UNET I could find.

Hi!

No, this is not possible. If you want to use steams networking API (including their peer-to-peer connection, automatic proxy, nat-punch-through, etc.) you have to write your own networking layer on top, or use a third party solution which allows you to switch out the underlying networking layer (like Bolt).

If you want to use UNET, you have to go through matchmaking and connection service.

2 Likes

Ahhh, ok. Thanks for the info!

I dont see why it would not be possible to use Steamworks to connect players with NAT punchthrough to a unet host (and then avoid the unity relay server) :s

Yeah, it is totally possible to use steamworks lobbies for basic matchmaking at the very least. All you’re doing is passing around connection info so there’s no reason steam lobbies would work any less than some webservice or w/e other matchmaking you would use.

SteamMatchmaking.SetLobbyData(steamIDLobby, "publicIP", externalIP);
SteamMatchmaking.SetLobbyData(steamIDLobby, "internalIP", internalIP);

Using the actual steam connection and punchthrough I suspect is also possible using https://docs.unity3d.com/ScriptReference/Networking.NetworkTransport.ConnectEndPoint.html but I have not tested so I could be totally wrong about that one.

Being able to use Steamworks NAT punch through have the huge advantage of not needing to host a NAT facilitator yourself (of course you need to be on Steam first…)

Maybe that’s a feature you should add to your plugin thegreatzebadia :wink:

1 Like

Don’t worry @S4UC1SS0N , it’s all in the works (assuming it’s even possible).

If you release it as a cheaper and dedicated plugin, tell me :wink:

** @thegreatzebadiah what’s up with that ?**

@Razmot Unfortunately no progress on that front yet. It probably won’t be until after my studio releases our game sometime around the start of the year. Until then I’m pretty much booked solid.

Sorry for bumping this old thread. This is one of the many threads I stumbled across when researching this topic. Cross-posting here to share my solution for others.

More info: Unity UNET HLAPI and Steam P2P networking - Blog - RJ Arcade

Sample project: GitHub - rjtngit/unet-steamworks: Example integration of Unity's UNET HLAPI and Steamworks P2P networking using Steamworks.NET.

Thanks so much for sharing! I’ll be sure to give this method a go. Your write-up looks great, but would it be OK to ping you with a question or two if I run into difficulties?

Yes! And please share if you find a better way to do something.

Nice! Is it possible to use oculus matchmaking in a similar way?

Excellent information @rempelj

I’ve never worked with Oculus networking so can’t say for sure. I had a quick look at their P2P docs and yeah, it looks like you could probably implement it in a similar way.

Edit: To expand on my answer a bit… Simplified from my article posted above:

The 3 main pieces you need to work out are:

  1. Connecting:
    -Host creates room/lobby
    -Clients join and request p2p connection
    -Host accepts p2p connection
    -Both client and host create NetworkConnections to represent the p2p connection

  2. Sending data:
    -NetworkConnection.TransportSend is overridden to send data directly to the peer instead of through UNET

  3. Receiving data:
    -Poll for data and pass it to the appropriate NetworkConnection’s TransportReceive function

Oculus networking seems to have everything you need to accomplish this.

Hey @rempelj , I’ve had a go at porting my existing UNET stuff across to Steam P2P using your approach. Thanks again for the awesome docs and sample project!

So far, it seems to basically work, but with some serious performance issues. In my initial testing with a single client and host, the client starts off synchronized, but drops further and further behind as the game progresses. I’m streaming state updates from the host to client and a decent rate (up to 30Hz depending on what’s happening in the game world.) It feels like Steam P2P messages are not being sent in real time, but are being queued up and arriving effectively 0.5x realtime or thereabouts.

Perhaps the P2P traffic is being throttled by Valve somehow? Don’t think I’m sending a totally crazy amount, typically somewhere in the region of 10kB/s I would guess. Maybe there is something I have to do in the Steamworks app configuration side of things… I was wondering, have you encountered anything like this during your dev efforts, and/or are you aware of any Valve/Steam tools I could use to diagnose the issue?

Cheers!

EDIT: Think I’ve figured out what was going on - the Update() method in SteamNetworkManager appears to only process a single P2P packet per frame. I’m sending a bunch of packets per frame, so it’s inevitably falling behind over time.

Changing:
if (SteamNetworking.IsP2PPacketAvailable(out packetSize))
to
while (SteamNetworking.IsP2PPacketAvailable(out packetSize))

seems to fix things nicely! Not sure if this will help anyone else, but may as well post it up in any case.

1 Like

@stevesalmond Nice find! Thanks for sharing.