UNet and Nat Punchthrough. It can be done!

NAT-Traversal-for-UNET

Overview
An example implementation of NAT Traversal combined with Unity’s UNet HLAPI. Attempts to establish direct connections between players using a combination of NAT Punchthrough and automatic port forwarding. Falls back to UNET’s relay servers only when absolutely necessary. When initially connecting the first connection to succeed is used, but if a direct connection succeeds after a relay connection is already established the direct connection will replace the relay connection.

Make sure to take a look at the README.

But Why?
The primary motivation for creating this was so that I could be less dependent on Unity’s relay servers. For one, they are bandwidth restricted, and they seem to introduce some pretty high latency. Plus it’s just one more point of failure that us lowly developers have absolutely no control over. This solution should mean that connecting through Unity’s relay servers is almost never necessary.

Requirements
Unity 5.2 or above
RakNet and Open.NAT dll’s are included for windows but you’ll have to compiler your own for Mac / Linux

Known Issues
RakNet doesn’t work with web sockets, so no web builds.
Needs lots of testing

Download
NAT Traversal for UNET

Other
If you are just looking for NAT punch-through without all the other bells and whistles I’ve got a simpler example here: NATPunchthroughClient

I’m putting this out there for anyone to use. I’d really appreciate any feedback / testing that the community can provide. Another set of eyes always helps and I’m really not positive I’ve got everything set up 100% correctly. If you download the project and can’t get it working please report back here and make sure to mention the router models involved. RakNet is a pretty mature library so if something goes wrong it’s probably a problem in my code and probably something easily fixed, or you just happen to have one of the few router setups that punchthrough doesn’t work on.

You are welcome (and encouraged) to submit pull requests to the repo if you find yourself adding to or extending the functionality in useful ways.

Thank you!

5 Likes

A version that used the relay as a fallback would be amazing! I would also love to contribute to this, as NAT punching should be in UNET!

1 Like

Feel free to clone the repo and submit a pull request if you come up with any good changes / improvements. I’m open to collaboration.

I might see if I can put together a more complete example with port forwarding tomorrow, but no promises. I’ve got to work on the actual game at some point you know!

If you wanted to try and implement the fallback to relay yourself that would honestly be amazing. No pressure or anything though ;p The hard part would be creating a router setup where punchthrough fails so that you can properly test that the relay works when punchthrough doesn’t.

Hello,
I would like to ask if i can use google services real multiplayer to MatchMaking and let use uNet HLAPI to Mange the game?

I’m not familiar with that service in particular but in general it doesn’t really matter how you do your matchmaking, as long as you somehow pass around the external and internal IP of the host to connect to. If using the NATPunchthroughClient you also need to include the raknet GUID. In the example here I do it by including it in the match name that I create on UNet but I’ve also done it before using a custom php script and a database, or via the steam api. As long as you’ve got some way to pass the connection info it’s all gravy.

Holy shit haha, I was just googling around for NAT punchthrough (again), and found my own post I posted last year when UNET came out. Then I saw that you had replied, YESTERDAY, with this! What are the odds!? Thanks a lot, I will definitely try this out in the near future!

1 Like

How would I go about implementing RakNet’s relay server so I don’t have to use Unity’s paid (and expensive) relay servers?

1 Like

I’m honestly not sure, I only theorized that it may be possible. I have no plan of implementing that functionality myself because I think NAT Traversal is going to handle the vast majority of cases anyway. That being said, you are more than welcome to contribute to the project on github. The ability to use self hosted raknet relays would be amazing. There is some advantage to not hosting your own though, like not having to worry about having servers physically spread all over the world or load balancing / connecting to closest server.

Note that using RakNet will lock you out of using Web builds (and any other platforms that don’t allow real sockets and pthreads).

I use custom RakNet networking and really like it, but it comes with some baggage.

1 Like

Thanks guys! I’ve decided not to try to implement relay server, I’ll be contributing to the project though (direct connection → port forward → NAT Punchthrough).

2 Likes

Thumbs up. It would be awesome if you guys could manage to develop some kind of stable drop-in solution for this.

1 Like

I think I just got all this working. Direct connect, punch-through, and relay connections are all started immediately. The first connection to succeed is used. If for some reason a relay connection is made first but then a direct connection is later established via punch-through the direct connection replaces the relay connection seamlessly. This means that players can connect as soon as possible but they won’t be stuck sending data through the relay when a direct connection is possible just because punch-through took a little too long. Best of both worlds!

Oh I’ve also got automatic port forwarding implemented via Open.NAT.

I’ll post an update as soon as I get the code cleaned up a bit.

Awesome! I’m just getting started on my version :smile:

How do you check if the direct connection, NAT punchthrough connection, or Open.NAT connection didn’t work? Is it the same way we’d check to see if the player is connected with standard UNet?

I just posted an updated version here with all the promised features :slight_smile:

Ummm, right now I’m not doing anything with failed connections. Definitely something that should be looked in to. Right now I think OnClientError will be called on the NetworkManager if the relay connection fails but that’s it. Ideally we’d want to catch the errors from the other clients as well. We’ll know connection has really failed when we’ve received errors from all three.

1 Like

Can anyone help me out with a different problem I’m having? Underwater Effect? - Unity Engine - Unity Discussions

I will get to playing with this as soon as I am able and will provide feedback.

Just letting everyone know that my other thread was closed by a mod. Here is the reason given (emphasis mine):

I sent some probably unnecessarily angry messages back because I think both threads are pretty relevant. This one being the simplest possibly example of NAT Punchthrough and the other being full NAT Traversal (same reason I created separate github repos). Hopefully they’ll unlock it, but probably not so I’m updating all of the links and the information at the top of this thread to point to the newest latest greatest stuff. I’ll make sure to include a link to the punch-through only example that this thread was originally about because someone may still find it useful.

1 Like

It’s actually really not cool that you are taking a private conversation and publishing it live. Please be respectful of this.

1 Like