How did you build your communication layer?

A question for people who developed a client-server multiplayer game (that is, no uNet or Photon, but hosting your own server): How did you build your communication layer?

I tried using WCF - but Unity does not seem to support neither full duplex, nor DataContracts.

Then I though about using Sockets, but that led me to a dead end as well, as it seems like proper usage of sockets, and smart serialization of objects is not something that is very well documented.

So, now I feel like I’m "back at the “drawing board” trying to figure out the correct way the build the communication layer for my game.

Ideas? What did you guys do, and how did it work for you?

The question is way to unspecific. There are a multitude of dedicated network engines out there each with it’s own target field. It highly depends on the kind of game and what information you need / want to send.

When you said you want to host your own server i guess the player count is rather low / limited? So you don’t really need scalability. I don’t see why you don’t want to use uNET. You are not forced to use the matchmaking service Unity offers. The sole networking components just wrap around their own low-level API which in turn wraps around the normal .NET sockets (or web sockets in case of WebGL builds).

If you really want to roll your own way / protocol you usually would create a specialized implementation. Because implementing a general / abstract implementation would be almost a waste of time since that’s what uNet already does. General use-case network engines always have a trade-off between being versatile and being efficient. Yet uNet already provides and optimised way of transferring common object information based on Unity GameObject / Component model.

But again it depends on the kind of game. For example Quake3 / live works completely on server snapshots. So all information of the current gamestate that is relevant for one player is gathered on the server, packed into one compressed snapshot which is send to the player. Due to the BSP nature of the world the server actually tells the player what parts of the level can be seen by him. Other player objects are not persistent objects on the client but are rather “recreated” from the snapshot information. The engine generally interpolates between the last two snapshots.

On the other hand something like an RTS game has completely different difficulties to deal with. The send rate is generally lower and the amount of data send higher. For turn based games (card games) you usually don’t have a constant sendrate at all.

How you want to encode your data in a network packet / network stream is up to you. Really, don’t use .NET BinarySerialization it’s way to verbose as it has to contain the full class names of the objects involved (full means: assembly name + namespace + classname). As part of Unity’s low level API they offer the NetworkWriter and NetworkReader class. They can serialize all primitive types as well as most Unity types into a compact byte stream. This is basically an equivalent of the .NET classes BinaryReader and BinaryWriter but optimised for smallest footprint and extended for several Unity types. So with those you can easily design your own protocol. Keep in mind that “serializing” a Transform / GameObject / NetworkIdentity reference depends on the NetworkIdentity component.

A large portion of Unitys Networking system has been released under an MIT license. Only the low-level API (where implementation highly depends on the underlying transport) is part of the Unity engine core. But again this is seperate from the paid matchmaking service Unity provides for uNet.