Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm (de)serializing some datastructures for a network-multiplayer game, and for each datastructure that's to be (de)serialized, I want to define the order of (de)serialization only once for maintainability without any additional bandwidth overhead, and as little performance cost and extra typing as possible.

I can use C#'s abstract class methods to achieve my goal, but there's several problems with doing so:

  1. performance: adding an additional abstract method call to each (de)serialization operation isn't ideal

  2. extra typing: I have to needlessly initialize all variables I'm deserializing because C# won't allow me to pass "ref" and "out" parameters interchangeably

How can I avoid duplicating the definition of a datastructure's (de)serialization while also avoiding some or all of the above issues, and continuing to avoid any additional bandwidth cost?

(ProtoBufs and BinaryFormatter both seem to use some additional bandwidth for metadata to describe the "payload" data, and XmlSerializer, DataContractSerializer and NetDataContractSerializer are all xml based and therefore more bandwidth intensive than a straight binary serialization. I also toyed with delegates and reflection, but this solution came to me most readily):

public struct ControllerSnapshot
{
    public Vector2 m_lStick;

    static private void Op(ref float lStickX, ref float lStickY, Op<float> op)
    {
        //define (de)serialization order here once and only once
        lStickX = op.Invoke(lStickX);
        lStickY = op.Invoke(lStickY);
    }
    public ControllerSnapshot(uLink.BitStream bitStream)
    {   
        OpRead<float> opRead = new OpRead<float>(bitStream);
        float lStickX,lStickY;
        lStickX = lStickY = 0.0f;//2.can't use "out"; have to match Op's "ref" params
        Op(ref lStickX,ref lStickY,opRead);

        m_lStick = new Vector2(lStickX,lStickY);
    }
    public void Serialize(uLink.BitStream bitStream)
    {
        OpWrite<float> opWrite = new OpWrite<float>(bitStream);
        Op(ref m_lStick.x, ref m_lStick.y, opWrite);
    }
};

//in order to make the above work this needs to be defined:
abstract class Op<T>
{
    public Op(uLink.BitStream bitStream)
    {
        m_bitStream = bitStream;
    }
    abstract public T Invoke(T arg);

    protected uLink.BitStream m_bitStream;
}
class OpRead<T>:Op<T>
{
    public OpRead(uLink.BitStream bitStream) : base(bitStream) { }
    override public T Invoke(T arg)
    {
        return m_bitStream.Read<T>();
    }
}
class OpWrite<T>:Op<T>
{
    public OpWrite(uLink.BitStream bitStream) : base(bitStream) { }
    override public T Invoke(T arg)
    {
        m_bitStream.Write<T>(arg);
        return arg;
    }
}   

//by contrast, the "obvious" code duplicates the order of (de)serialization, which I
//want to avoid, especially as (de)serialization becomes increasingly complex:
public ControllerSnapshot(uLink.BitStream bitStream)
{
    float lStickX,lStickY;
    lStickX = bitStream.Read<float>();
    lStickY = bitStream.Read<float>();

    m_lStick = new Vector2(lStickX,lStickY);
}
public void Serialize(uLink.BitStream bitStream)
{
    bitStream.Write<float>(m_lStick.x);
    bitStream.Write<float>(m_lStick.y);
}
share|improve this question
2  
fwhoa, this is a really long question. –  Shotgun Ninja Apr 24 '13 at 21:07
    
ProtoBufs uses no additional metadata unless you actually need it for something. Using the .proto IDL files can help reduce redundancy and make bad (for serialization) class designs easier to spot. –  Sean Middleditch Apr 24 '13 at 21:44
    
Are long questions automatically bad? I think I expressed all the relevant information pretty concisely -- how else could I get the problem across concretely? –  Nathan Frost Apr 24 '13 at 23:04
1  
@Philipp Don't be so sure - game networking has some fairly specific requirements and differences, compared to other kinds of serialization. –  Andrew Russell Apr 25 '13 at 11:04
1  
@Philipp: The question was originally posed on stackoverflow with the "no additional bandwidth" requirement omitted -- some programmers gave me some good solutions that all seemed to increase bandwidth, so I thought gamedev might be more performance-conscious. –  Nathan Frost Apr 25 '13 at 19:12
show 6 more comments

closed as off-topic by Josh Petrie Dec 2 '13 at 17:45

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Programming questions that aren't specific to game development are off-topic here, but can be asked on Stack Overflow. A good rule of thumb is to ask yourself "would a professional game developer give me a better/different/more specific answer to this question than other programmers?"" – Josh Petrie
If this question can be reworded to fit the rules in the help center, please edit the question.