Network list with event when value in list element changed

Hello

I have a simple struct/class PlayerAsset, with string AssetName and int Quantity. I know I can hold it in NetworkList and it will send notifications to the clients when the list itself changed (list element was added/deleted). The problem is, I don’t know how can I implement behavior like below:

private int quantity;
public int Quantity
{
    get { return quantity; }
    set 
    {
        if(quantity != value)
        {
            quantity = value; 
            QuantityChanged?.Invoke(quantity);
        }
    }
}

public event Action<int> QuantityChanged;

Right now server handles changes using Rpc, when quantity value changes it sends to specified clients the new value and the asset name. Syncing the whole list and listening for the changes of its elements would be easier/ less messy to implement tho. Is there a solution to this problem?

Yeah, no.

I mean perhaps “easier” but that mustn’t be your goal here. Consider that such a list would needlessly send each player’s data as a whole, including the player names which - if not properly safeguarded, could contain Shakespeare’s entire works in a single string. So you may possibly be synchronizing Megabytes, but definitely a lot more compared to just sending the new quantity respectively the new data entry.

Network programming is mostly about sending only the data that is necessary, as infrequently as you can get away with.

To that end, I would strongly advice against putting that player name string in the same struct with whatever else.

Because that “else” will change at a different rate and for different reasons than the player names. Perhaps the player names never change once the game commences? In that case, the player names definitely don’t belong in the same data struct together with dynamically, frequently changing data.

It is generally preferable to not have a NetworkList<MyData> but rather have multiple NetworkList, one for each kind of thing that needs synchronizing like player name, player health, player’s active weapon index, player’s active avatar choice, and so on. Given just a little discipline those would all have the same length (number of items) if need be, but they’d synchronize only when one of them changes.

Btw, my examples are terrible. You don’t want all player’s data in lists to begin with. Since each player changes a weapon or avatar individually, this should not trigger a synchronization of every player’s data of the same type. That in itself is very wasteful (ignoring NGO 2.0’s new delta list transfers).

Thank you for reply. So in order to keep list of resources for each player (imagine Factorio, Anno series or Port Royale with tens of resources for each player), creating local list with resources for each client, server list containing all resources and sending notifications about add/modify using RPC would be better than network list? From your response I conclude that NetworkList is made mostly for small data sets like single small string or int rather than complex stuff?

Yes, in that case you want a NetworkList per resource type, not a NetworkList of all resources.

In fact I probably wouldn’t use NetworkList at all for that kind of game. It would just create far too much traffic to synchronize every resource change from and to all clients at the network tick rate (30 Hz by default).

Even if you lowered the tick rate to 10 Hz, which is sufficient for those kinds of games, it would still be wasteful to update resources at this frequency. Consider that for Player A it doesn’t matter whether he sees Player B’s stone resource accurately, or with a 1 second delay. I’d send these resources at a fixed, artificially lowered interval via RPCs that still feels “realtime enough” for everyone because you can cut down the traffic for those tenfold or more!

It depends on your game mechanics, but there is a possibility that you don’t need to sync at a fixed rate.

Player A’s client may be able to simulate locally (= predict) what resources player B gains/loses depending on the game state. You will only need to sync on specific events, such as when a new player joins or specific gameplay events occur (i.e. player B spends resources to build something).

And to add to that, if there is no value change in between two intervals then of course you just don’t send an RPC because that’ll likely be the most common case.