Network bandwidth is the amount of data the network can transfer in a given time. Here are the things that can be done to lower the amount of bandwidth used.
Bit Packing
The goal is to use as few bit's as possible to send any type of data. For each variable limit the range of it's possible values and compress it to only use the bit's needed for that data.
Bool: Can be sent as a single bit.
Integers: Specify the possible range of values and then use the minimum possible number of bits. So a int with values between -10 and 100 only need to use seven bits.
Floats: Set the min/max values and then the number of bits to encode the value with. So a float between 0 and 5 with 10 bits will get a precision of 0.00488.
String: String is a simple zero terminated string. It can be compressed in Base64 but the number of direct strings should be kept to a minimum.
StringId: Instead of sending strings put them in a array and send the number as a integer with the least number of bits. By using more then one array one can get smallest possible integers.
Vector3: A vector3 can be sent as three floats, each one compressed by itself.
Reference
Network Serialization and Routing in World of Warcraft - 2013
Packing Integers - 2002
Scalar Quantization - 2002
Transmitting Vectors - 2002
Topics in Quantization for Games
http://cbloomrants.blogspot.com/2020/09/topics-in-quantization-for-games.html
Compression
Using some form of compression (like gzip) on the stream of data or a single package. Huffman compression (per-packet).
Patching / Delta compression
Only send data when it have changed.
Prioritize
For each object a priority is calculated per-client. Each frame the highest priority objects are synced to the each peer. The final priority is based around the following data.
Relevance: How noticable this object overall for a player in a game.
Bonus: This increase each frame and reset when the object is sent to the client. That way we are sure that the object will be sent sooner or later no matter what.
Update Rate: How often we should try to send an update about this object.
Filter
One good way to lower the data sent is to not send things at all. The player do not need to know if someone at the other side of the world moves or that a ghost move if he can not see ghosts. This is done by filtering out the objects that a node need to know about by using geometric data, zones or game rules.
Geometric: If a object is to far away we do not need to send updates for it.
Zones: Split the world into areas and only the ones that matter to the player is synced to the player. If the player is inside a dungeon only things in the dungeon need to be sent to him.
Rules:
Reference
Bitcrunching numbers for bandwidth optimisation - 2014
The importance of packet count - 2014
Network bandwidth mathematics; peer-to-peer versus client/server - 2008