3
votes

I'm working on a server-based multiplayer game written in C#. The server and the client shares code and each object has the same int ID. I want to make the networking to be light as possible, by sending only the changed data.

The game has classes, which have numerous fields/properties, and they often change. I'm seeking a way to detect when these values change and send these values to the client side.

Basically, this algorithm:

  1. Flag object when it's changed
  2. With the changed objects at network Tick:
    1. Compare each property with their previous state
    2. Send only the changed values
    3. Store old values
  3. Receive them on the client side
  4. Instantiate the same type of object, or find it by ID
  5. Set the new values

Of course, .NET Reflection may be eable to solve this problem, but iterating throuh 1000 object and their properties in each Tick, would be a bottleneck in performance.

I can send the basic types (int, float, vector), and maintain connection. My questions are these:

What's the best approach to send an object's Class and instantiate it?

How should I detect property change and how to serialise properties so I can find their "pair" on the client when receiving.

1
"Of course, .NET Reflection may be eable to solve this problem, but iterating throuh 1000 object and their properties in each Tick, would be a bottleneck in performance." And you've profiled this rather than just assuming, yes? It may not be the most efficient method but if it's efficient enough for your needs, don't complicate things.Sean Middleditch
Its kind of obvious that this wouldn't work even without any profiling. If someones suggest something even more crazy like using ORM and database to find changegs would you still recommend profiling first?Kikaimaru
@Kikaimaru: yes, actually, I would, because what you think is "obvious" is very much not so. There are released online games using the OP's method, and ones using databases and ORMs for change detection as well. What makes you think they're inherently too slow for the OP's completed unstated needs?Sean Middleditch
@SeanMiddleditch: Can you give a link for sources for such games?Kikaimaru
@Kikaimara: That's generally not legal, so no. :) Am I talking about twitch shooters like Quake? Of course not. Not every game needs to spit out updates at 30-60hz. The OP has not indicated any kind of timing needs, so he's possibly chasing a phantom problem that doesn't exist. This is why we test and profile and not take the random "it'll be too slow" advice from people on the Internet at face value. :)Sean Middleditch

1 Answers

3
votes

You can create something like this:

class Mob {
private int _health;
public int Health
{
   get { return _health; }
   set { _health = value; DirtyFlags |= MobDirtyFlags.Health
}
}

this means a lot of code for each property

Or you can have some custom dictionary and every change in that dictionary would be tracked, so

mob.Properties["Health"] = 10; would track that you changed something.

This is how Mooege (Diablo 3 emulator) does this.

First approach can be rewritten with aspects (probably some custom code that will generate all that code that is written above at runtime via Reflection.Emit or something similar). Or if you know what will all your entities look like, you can generate classes for them from some templates (using something like T4)

as for serialization, this is good enough: (key: int, value: object) where key would be some enum like ActorProperties { Health, Strength, ...}