#Implementing sparse change tracking for multiplayer entities

1 messages · Page 1 of 1 (latest)

grand crown
#

I'm trying to come up with an elegant solution to track changes made to the values of my game entities so that those changes when they happen on the server can be synchronized to clients who can then apply the changes. I'm using protobuf-net for my serialization.

essentially what I've come up with so far is that the game entity base class has a queue of changes:
private readonly ConcurrentQueue<ChangedProperty> propertyChanges = new ConcurrentQueue<ChangedProperty>();

#

ChangedProperty is defined as:

    public abstract class ChangedProperty
    {
        public ushort Key;

        public abstract object GetValue();
    }```
#

this would mean that each property that needs change tracking would need to be implemented like so:

        public int TestValue
        {
            get
            {
                return this._testValue;
            }
            set
            {
                if (this._testValue != value)
                {
                    this.propertyChanges.Enqueue(new ChangedPropertyInt32 {  Key = 55, Value = value });

                    this._testValue = value;
                }
            }
        }```
#

clearly this is not an elegant solution... but I think it should be relatively fast. I thought about doing something using reflection but felt that would likely be a lot slower

warm echo
#

You should be sending state updates at a fixed interval

#

You can use bit flags to denote whether something has changed or not

#

If you're trying to do delta compression, then I don't think you're going to get far with protobuf unless it directly supports variable width encoding.

#

Apart from that, I don't know what you're asking. Assigning IDs should all be done on the server, then the instantiate RPC should be sent as a reliable, ordered message.

grand crown
#

I'm planning on doing fixed interval state updates, but I'm trying to come up with a way to sparsely send updates to clients when a few properties change on an object that might have dozens. For example if the 'Hitpoints' property changes between updates, i want to send the new value, but not re-send all the other object state that hasn't changed

warm echo
#

Yeah, your client will need to communicate which states it's seen

#

and the server builds the delta based on that

grand crown
#

I don't think the client needs to tell the server what it knows about? the object on the server only needs to keep track of what changes it's doing to the entity and then each update the dirty properties would get flushed to clients... I'm using TCP for networking for this

#

so i'm not super worried about clients getting majorly out of sync

warm echo
#

Is this like a card game?

#

or fps?

grand crown
#

it's a sim game

warm echo
#

dont know what that means

grand crown
#

simulation. like Rimworld or SimCity

warm echo
#

do yourself a favor and stop using tcp

#

If one packet gets dropped, the entire stream stops

grand crown
#

mmm, I appreciate your opinion but no thank you.

warm echo
#

and people stop getting updates

#

Can't help you beyond that, because nobody uses TCP for realtime stuff like this

#

good luck man

grand crown
#

you're wrong, but okay. i didn't come here to argue

warm echo
#

I'm not arguing with you, I'm just telling you that nobody does that unless it's the equivalent of a card game

#

like I said, good luck

#

you dont need to respond

grand crown
#

minecraft uses TCP.

warm echo
#

the entire world state also locks up at the slightest inconvenient network issues. They're moving to UDP in the new microsoft version.

#

If one packet drops, the entire transmission freezes

#

this doesn't seem to be an issue for you, so I'm not going to bother you anymore

warm echo
#

@grand crown Looking back, I never really answered your initial question.

You'll need to quantize your data if you want to compress it. This just means shifting the decimal and converting to integer. Integers compress a lot nicer than floats. Then protobuf does the variable width encoding.

You'll need to keep a past state of everything. 1 or 2 seconds of states is fine. Since you're already doing a reliable approach, only the server will need to monitor which states it's sent to who. Each object's state will need to keep track of which players its been sent to, etc

#

When objects go out of range or stops moving, you can simply stop sending data. When it's back in focus again, you'll need to send a fresh full non delta state. If an object is in-focus but not moving, you can send a single bit flag to denote that it hasn't moved and you won't need to resend the full state.

#

When you're storing state data, you'll need to store it in quantized fixed point form, in order to compute the deltas properly

grand crown
#

you're answering a question yes but it's totally unrelated to what i asked

#

i'm not compressing data

#

i'm not delta-transferring data

warm echo
#

I don't know what you're asking then

#

so you're going to have to clarify

#

If you're asking how to synchronize the variables of your networked classes automatically, then a code generator is the most efficient way, and they get updated with the state.

grand crown
#

no, forget it