Monday, June 14, 2010

Death Zone Zero: Minor Update: Client Server Network

The Battle Server is slowly starting to take shape. Players can log-in, get their unit data from the database, and load units on the battlefield. Can't control them yet though. But with the work I've done in the single player demo, the template is there. I just need to add the multiplayer network part to it.


One thing I don't like about Unity is the lack of better serialized data transmissions across the network. I made a formal request about it here:
Oftentimes I need to send a bulk of data to the client to initialize his data. I have 2 options for doing this: RPC (Remote Procedural Call) or a OnSerializeNetworkView function.
The problem with using an RPC is you pass the data using arguments. My data includes arrays of classes so using an RPC is problematic.
I can use instead a OnSerializeNetworkView function and serialize the data into a stream. The problem with the current OnSerializeNetworkView function is you can't control when exactly it gets called. OnSerializeNetworkView is meant to be called continuously, and has to be attached to a certain Network View.
I need a Serialize function that would get called only when I tell it to, much like an RPC.
Having worked with the Torque Game Engine, Torque has what they call a NetEvent, basically a one-shot serialized data transmission from/to Server and Client.
This is perfect for initializing the Client with data, or when the Client needs to submit a list of information to the Server (like when buying/selling multiple items from/to a shop).
And please, if this gets implemented, please make it available to the Unity free version.
My guess is allowing a BitStream to be a valid argument to pass in an RPC is the most straightforward way to do this.
Right now I'm faking serialization by turning my data into one long string and sending that to the client. This, I guess, takes up a lot of bandwidth since strings in Mono are 16-bit each character because of Unicode support.

That's ok, I tell myself. Just imagine the client is loading a web page. Heck, maybe even the average web page is larger than what I'm transmitting. And I'm not sending it every loop or something; its for initializing client data, so a one-time, large bulk of data transmission is quite allowable.

It makes me miss my days when coding in Torque Game Engine. You can squeeze all the bits of data you want as small as possible there. They have their own version of the BitStream: Like a normal stream you serialize your data, but the special thing is the compactness of the serialization. Transmitting a boolean requires only one bit, strings can be compressed to save space, and you can specify by how much bits an integer or float is going to take when serialized into the stream.

For example, say you have an integer variable health, which in your game goes only in the range 0 to 100. You can then specify the health variable to be serialized to only 7 bits (essentially creating a 7 bit integer, which goes in the range 0-127), since its value goes only up to 100. You saved 25 bits, assuming it was a 32-bit integer, a whopping 78% of the original size.

They even have what they call a StringTableEntry. Basically used for strings that get sent over the network frequently, like usernames or preset error messages. What happens is the first time its sent, it gets sent as a normal string, but the next time, it gets sent only by a reference ID number to save bandwidth.

No comments:

Post a Comment

Made me post. 0/10.