RakNet Unity compatibility

Hello. I'm looking to create a standalone dedicated server for my game, based on a RakNet (going to just extend the existing master server). I heard that Unity and RakNet are fully compatible, but never seen any simple examples of that.

Is anyone able to give such examples? Please, help :)

Thank you.

First thing is you need to get the master server code, and since by default the version that is on the masterserver download area of 0.1.0 doesn't compile straight up, you need to fix a missing include and a few other things.

Here is the fixed version for VS2008.
I also already have it precompiled so you can just run the executable if you like from the debug folder.
Second, get ahold of the tester, make sure you can connect on your network to this master server build from the tester, once you do that, you can then test from unity and see it connect, that is the first steps in getting this up and running.

96273--3736--$visualstudio2008_166.zip (7.1 MB)

Part 2:
Download the Networking.zip file because you will need to review how it is setup for the different projects and they do have a chat example but that is not for a stand alone headless server. Once you have that code, create a new scene, add a terrain, a first person player and an empty game object. Attach the ConnectGUI script from under the Networking Scripts folder to that empty game object.

Change the remote IP to your server IP, and update the server remote port to that of your headless server, in the case of the project here (2008), the port is 12345. Leave the listen port alone.

Attach the Chat script to the Main Camera on the first person controller (got to see what we are doing right?) Update the Skin to use the bubbleskin.
(Ignore the start server button, I just haven't bothered removing it, typing this up fast for you to get you under way)
Now test your connection, here is a shot of the scene setup.

96282--3737--$picture_4_185.png

Part 3:

If you have retrieved the files thus far and setup the environment correctly, have your PC running the master server, click on Connect within Unity, and you should see yourself connect, then stop the test and you should see yourself disconnect. End result should be something like the following image:

96283--3738--$masterserverdisconnected_184.jpg

Part 4:
simple example done
Now obviously this can easily be expanded on to the N'th degree. Just hop into the networking exmaples that the wonderful people at Unity have put together and see how the integrated server component works then take the headless code and expand on it for a stand alone server base. That about wraps this example up for a quicky like you asked unless you have further specific details you want me to cover.

A+ for quality zumwalt :smile:

The only thing I would add was that the connection tester code didn't compile for me on VC++ 2005 Express Edition, but shaun provided a nicely working copy here:

http://forum.unity3d.com/viewtopic.php?t=14419

Hi, thanks a lot for such advanced answer :)

:sweat_smile: seems that I've been a little inaccurate. I forgot to notice that I already have a project that actually represents a server/client functionality, it uses "network view" and stuff and I just wished I could see how to use the network view when I have a Unity3D as a client and a RakNet as a server.

As I understood there is a piece of code in a MasterServer.cpp that processes all packets:

void ProcessPacket(Packet *packet, char* caller)
{
    switch (packet->data[0])
    {
        case ID_DISCONNECTION_NOTIFICATION:
            print_log("%s: %s has diconnected\n", caller, packet->systemAddress.ToString());
            break;
        case ID_CONNECTION_LOST:
            print_log("%s: Connection to %s lost\n", caller, packet->systemAddress.ToString());
            break;
        case ID_NO_FREE_INCOMING_CONNECTIONS:
            print_log("%s: No free incoming connection for %s\n", caller, packet->systemAddress.ToString());
            break;
        case ID_NEW_INCOMING_CONNECTION:
            print_log("%s: New connection established to %s\n", caller, packet->systemAddress.ToString());
            break;
        case ID_CONNECTION_REQUEST_ACCEPTED:
            print_log("%s: Connection to %s accepted\n", caller, packet->systemAddress.ToString());
            break;
        case ID_CONNECTION_ATTEMPT_FAILED:
            print_log("%s: Connection attempt to %s failed\n", caller, packet->systemAddress.ToString());
            break;
        case ID_DATABASE_UNKNOWN_TABLE:
            print_log("%s: ID_DATABASE_UNKNOWN_TABLE to %s\n", caller, packet->systemAddress.ToString());
            break;
        case ID_DATABASE_INCORRECT_PASSWORD:
            print_log("%s: ID_DATABASE_INCORRECT_PASSWORD to %s\n", caller, packet->systemAddress.ToString());
            break;
        case ID_DATABASE_QUERY_REPLY:
            print_log("%s: ID_DATABASE_QUERY_REPLY to %s\n", caller, packet->systemAddress.ToString());
            break;
        case ID_NAT_TARGET_NOT_CONNECTED:
        {
            SystemAddress systemAddress;
            RakNet::BitStream b(packet->data, packet->length, false);
            b.IgnoreBits(8); // Ignore the ID_...
            b.Read(systemAddress);
            print_log("%s: ID_NAT_TARGET_NOT_CONNECTED to %s\n", caller, systemAddress.ToString());
            break;
        }
        case ID_NAT_TARGET_CONNECTION_LOST:
        {
            SystemAddress systemAddress;
            RakNet::BitStream b(packet->data, packet->length, false);
            b.IgnoreBits(8); // Ignore the ID_...
            b.Read(systemAddress);
            print_log("%s: ID_NAT_TARGET_CONNECTION_LOST to %s\n", caller, systemAddress.ToString());
            break;
        }
        default:
            print_log("%s: Unknown ID %d from %s\n", caller, packet->data[0], packet->systemAddress.ToString());
    }
}

see, in the very end the "default" part. I thought it's a part that I should extend somehow, so I could use the "network view" functionality in RakNet, but I've never saw it work, only if you trying to connect to a server that doesn't exist. So I wanted to see if it's possible and how.

Also, for example, it would be great to see how to send an RPC from Unity3D to RakNet and vice versa.

Thanks.

Ok on to the next steps then, for you to identify your OWN packets / custom ID's.

Open MessageIdentifiers.h , scroll to the bottom...

// For the user to use.  Start your first enumeration at this value.
    ID_USER_PACKET_ENUM,
    //-------------------------------------------------------------------------------------------------------------

THIS is where you begin, you do NOT modify the MessageIdentifiers.h file, instead you create a new header file in your project, call it VladKIdentifiers.h and save it.

Now, in this file add the following code:

 enum {
   ID_CUSTOM_VLADK_MSG_1 = ID_USER_PACKET_ENUM, // Where ever ID_USER_PACKET_ENUM left off yours will start equal to that and go from there.
   ID_CUSTOM_VLADK_MSG_2, 
 };

Now, open MasterServer.cpp, find the line that says

#include "MessageIdentifiers.h"
// now below this line, add your header file
#include "VladKIdentifiers.h"

At this point, your master server can identify YOUR packets correctly. Now you are ready to use them. Add to the list of case statements the following above the default: line.

case ID_CUSTOM_VLADK_MSG_2:
   print_log("%s: INCOMING CUSTOM VLADK to %s\n",caller,packet->systemAddress.ToString());
   break;

Before I go any further, are you proficient with C++?

Disclaimer:
Do to Unity developers updating the masterserver code on a constant bases to improve it, avoid if at all possible any changes that you make directly to any RakNet code files. Do as much in your own as possible, although you will not be able to get around making modifications to MasterServer.cpp file, make a backup of this file in the event that you upgrade your masterserver code and keep your custom files in a seperate directory other than the folders that Unity creates by default for their projects as it relates to the master server project.

Wow! Now, we're talking :)


yes, of course, please, continue!
[quote]
Disclaimer:
Do to Unity developers updating the masterserver code on a constant bases to improve it, avoid if at all possible any changes that you make directly to any RakNet code files. Do as much in your own as possible, although you will not be able to get around making modifications to MasterServer.cpp file, make a backup of this file in the event that you upgrade your masterserver code and keep your custom files in a seperate directory other than the folders that Unity creates by default for their projects as it relates to the master server project.
[/quote]
...and thanks for this tip :)

Impass, I am stuck.
All I should have to do is something like
Network.SendRPC("ID_CUSTOM_ZUMWALT_MSG_2","other values that I want to pass serialized");

BUT there is nothing for custom send.
I tried creating an EGO, adding a script with

@RPC
function callMyMsg(str: string)
{
   Debug.Log("just made the call");
}

This goes no where... even when I use it as

function OnGUI()
{
    networkView.RPC("callMyMsg",RPCMode.All);
}

I am scratching my head at the moment.
All Raknet is waiting for is really a packet with the ID that I am passing it as the first object in the collection.. Unfortunately we have ZERO control over the library that is the internal client in Unity, so I am CLUELESS at this point as to how they implemented custom routines outside of there static ones.

Also, we probably can't do anything about it anyway, I just traced down the fact that the server code released ends at ID 70 and ours would begin at 71, however the server is sending 75, so there are 5 unrelated ID's floating around. The beta code is outdated against the Unity 2.1, we need updated networking code if we are to write our own custom master server.

Slightly overlooked along with the missing references in the code for the master server. Sorry but until the latest code or atleast an equal master server code against the release 2.1 is released, we might be on our own for writing a master server. As I had mentioned in another thread, RakkNet needs consistant packet data between releases, and since the packet ID's are currently off by 5 between 0.1.0 of the master server and Unity public release of 2.1, nothing I can do about this at the moment, I have no clue what those custom ID's are, without seeing the built in client code as a reference, we have to wait on them.

I don't know those ID names, these are equal to the header I defined earlier in this thread, we are missing their header for custom ID's which they do have but we do not have.

pity :( I wonder why there are no posts from Unity-developers?

Guys, you told us, that "MMO enabled". I think it's just a time to come here and show HOW does it enabled.

The problem is that the client version in 2.1, we are not given the custom ID's they have added to the list (which extends the server), now the code they posted for the masterserver for us to make our own, only includes the standard Rakknet ID's (as mentioned above to which file to find these). All of the standard built in ones end at 69, the 70'th one is the 'link' one that you start to use (or rather make your customID=lastID, probably should just leave it at that). Then the following ID's are user ID's to identify WHAT the packet is for and then you decide on the server how to handle that packet.

Unity has not divolged what there custom header file is that has their custom ID sets and what each packet ID is for, and I doubt they will, but you never know.

I want to keep this post within their custom implimentation and not expose an alternate implmentation of Rakknet and Unity (since that is entirely possible to do). The problem with using our own implmentation of Rakknet vs using theirs with the code they provide, is that there is no guarantee that our servers will talk to their master facilitator server and be able to communicate.

That really is the whole point in keeping to just their implmentation, to use their facilitator and master distribution for game announcment.

So their remains no way to use unity's built in networking library with a centralized server? Is their any update to this? If we were going to use a centralized server is the only option to use a some thing like smart fox or another custom set up?

Bill

I now have the current ID's they are using internally for the structure, I'll try to update this thread this weekend with further instruction based strictly on Unity's internal design and expanding the MasterServer code. There is also another thread in progress that describes how to use RakNet independent of the built in version by Unity.

zumwalt, please post those ID's you find out, and also further information on how to extend the unity's raknet implementation.
Sure there's lots of folks trying to do something like that, and i think that the best way for everyone is to cooperate and share all that is found out.

Regards

Better yet put it on Unify. I doing the same right now (I think the other thread you referred to was the one I posted in) and it would be massively useful just to get the protocol established.

IMHO, unity should let its community have access to the ID's used in the networking.

This would be of great help to programmers, and also would increase the engine's flexibility and interoperability. And it doesn't mean they're openning their code. It's just usefull info on communicating with the engine.

If this is not done, anyone who wants to build a game that supports more than just 32, maybe a little more, players connected at the same time, has to implement their own network, using only c# sockets.

This is just my opinion, and also a plea for unity team in order to make it easier and useable for us, users.

[Larus Response in other thread, not sure if anything has changed since 2.5 released]
RakNet's own message IDs end at 70 and ours start from there. The master server doesn't use any of the Unity game server/client messages so those are not included in that project (it's code base is completely seperate). He does use a few custom messages and those start at 200.

These are our current IDs.

ID_STATE_UPDATE = 70
ID_STATE_INITIAL = 71
ID_CLIENT_INIT = 72
ID_REMOVE_RPCS = 73
ID_REQUEST_CLIENT_INIT = 74
ID_PROXY_INIT_MESSAGE = 75
ID_PROXY_CLIENT_MESSAGE = 76
ID_PROXY_SERVER_MESSAGE = 77
ID_PROXY_MESSAGE = 78
ID_PROXY_SERVER_INIT = 79
ID_DATABASE_ROWID = 200
ID_MASTERSERVER_REDIRECT = 201
ID_MASTERSERVER_MSG = 202

I've not had any time to update this thread and I probably won't for a few weeks do to many factors on both a personal and professional scale. At the moment I have worked out a solution to get my current project to work seamlessly between Unity and Torque along with my own custom server solution. I still struggle with Unity and multiple servers so I am using Unity as a central server in a hub and spoke configuration and Torque for client interface. Unity can still only handle 1 server and can't very well do server transfers or have a single client talking to multiple servers. I have posted code in the forums somewhere on the internal changes needed done to Unity to make this happen, but since it was so long ago, I haven't bothered looking back. It is simply not a visible priority for them since it is not one of their focus tracks for Unity at the moment.

Anyway, long winded post over, those are the custom ID's you will need.

Thanx for sharing your knowledge with us zumwalt.

I wish things get better for you :wink:

Hi,

[quote=“zumwalt”, post:2, topic: 384332]
make sure you can connect on your network to this master server build from the tester, once you do that, you can then test from unity and see it connect, that is the first steps in getting this up and running.
[/quote]

How is it possible to connect the master server build from the tester?
Everytime I start Unitys Network.TestConnection() the ConnectionTesterStatus.Error gets returned. Any ideas what could be wrong? MasterServer, Facilitator as well as the ConnectionTester can be started without any problems. Nevertheless I get this error returned when the connection gets tested.