The Bandwith Art: learning how to optimize and improve your game network performance

A Roblox experience network performance is often ignored by beginner devs.

Who am I?

I am Wolo, the main scripter of the Roblox RTS game [( ✦ ) [RUSSIA] Conquest: Napoleonic Wars] ([RUSSIA] Conquest: Napoleonic Wars [Pre-Alpha] - Roblox) and ( ✦ ) Ages Of Iron 2: Punic Wars [Early Alpha]. I have been interested in RTS from 13. Over 2+ years of experience in Roblox scripting and 3+ years as freelancer.

I also have a short video about my experience as a Roblox RTS developer: My experience as a Roblox RTS games developer - YouTube

Important

This guide is aimed to help scripters, as there is not much other developer roles can do to optimize network usage, aside from reducing part count, compressing audio size… but this mostly helps loading time.

Essential thing to understand

When we talk about “bits” or “bytes” in this guide, we refer to the data size, less bits, less size.

A byte has 8 bits.

When talking about “replication”, we mean the server sending data to the clients / players for their devices to duplicate in their games

---------------------------------------------------------------------------------

Introduction: what do we mean by “network performance”?

When we talk about network performance of a Roblox experience, we mean how well the server is performing when sending data, how quick it sends the data, how fast it process the received data and how much it needs to send; the more data the server has to send to the clients, more time it will take, and therefore the laggier the game will feel.

This also includes making sure the server has enough resources to handle everything else, aside from sending and receiving data from the players. If the server CPU is at 100% usage and is completely occupied with other things, that means it will have to finish previous tasks before being able to send the data. Needing to send the data later means players wont see the game updating smoothly, meaning the game will feel laggy for them

Why is it important to have a good network performance / bandwith usage?

The reason was explained above, but basically, the longer the time the server needs to receive / send data to the players, the later will be the game updated for everyone.

But it also depends on the players internet connection!

Sure, but you can optimize your server network usage to still make a smoother experience for every player. Remember, if the network performance is bad, then does not matter how good the player internet is, the game will feel laggy.

How do I notice if my game has network performance issues?

This topic will be explained further in a section of this post, but you can notice it by seeing how much it takes for the server to do stuff. For example, clicking to move an object, and the game needing too much time to even start moving it. (In this example, it can also be very bad performance of the server in general)

---------------------------------------------------------------------------------

The Bandwith Art principle: less data, less processing time

The bigger the size of the data, the longer it will take the server to process and receive / send it, meaning more time before the game server continues. With this knowledge, the response is simple: just send your data compressed!.

Compressing the data that is sent to the server from players or the data that the server sends allows it to be smaller in size, meaning faster processing.

How do I compress the data?

I strongly recommend to make a modulescript that allows you to compress and decompress the data everytime with its functions.

But how do I compress!

There are different ways, some more effective than others. The most basic one and also probably the most ineffective is using arrays instead of dictionaries to send the data

From

{
Health = 120
}

To

{
120
}

Sure it reduces readability, but this basically removes a good part of the size of the sent data. But there is something better.

Buffers and bit32

(Bit32 is a complicated matter, here is a tutorial to learn it: [ADVANCED] Binary in Luau: Tutorial on Basic Computer Logic & Bit32 - Resources / Community Tutorials - Developer Forum | Roblox)

Buffers and bit32 allow you to compress the data even more, basically reducing the number of bits sent (understand bits as the size the data has). For example, if you want to send a number that is less than 128, it is pointless to send it the normal way.

Why?

Because Roblox assigns way more size / bits than necessary to send a number like that. Instead, we can make Roblox assign less using buffers / bit32. Learn this

{

--REMEMBER, A BYTE HAS 8 BITS
local NewBuffer: buffer = buffer.create(4) --The number in the parenthesis represents the bytes / size.

--buffer.write(BufferVariable, Data location in the buffer (in bits), value)
-- Remember, pay attention to the "i". buffer.writei8 is not the same to buffer.writeu8!

--The "i" stands for "signed", numbers that can only go from 0 to the max positive limit.
--The "u" stands  for "unsigned", numbers that can go both positive and negative, 
--but its max capacity is cut by half for positive numbers

--For example, a number of 8 bits can store 256 max. when signed, but only -128 to 128 
--when unsigned


buffer.writei8(NewBuffer, 0, 10) --Write 10 as a value in the "0" offset / location in 
--the buffer we created

-- When asigning more data, remember to account about previous values assigned size (in bytes!)
buffer.writeu8(NewBuffer, 2, 10)

RemoteEvent:FireAllClients(NewBuffer)

-----------------------------------------------------
--Reading the data!
local BufferToRead: buffer = NewBuffer

--The letter has to match! You cant read the values as unsigned if you wrote them as 
--signed
local Value = buffer.readi8(BufferToRead, 0) --buffer to read, the location of the data
-- you wanna get

Buffers have way more methods, bigger numbers capacity than what was demostrated here, but with this simple example you should understand how to use it. The documentation is here:

buffer | Documentation - Roblox Creator Hub

How do I know how much bytes do I have to assign when using buffer.create()?

Divide the number bits by 8. For example, if you want to write a number of 64 bits:

64 / 8 = 8 bytes!

This is too complicated! Is there an easier way???

Of course there is, some users have made modules that help with all of this of compressing / decompressing data!

Packet - Networking library - Resources / Community Resources - Developer Forum | Roblox - (made by @5uphi, probably the best networking module!)

ByteNet Max | Upgraded networking library w/ buffer serialisation, strict Luau and RemoteFunction support | v0.2.1 - Resources / Community Resources - Developer Forum | Roblox - (made by @Lightning_Game27)

Send less number! You do not need to send everything

Lets say you have this dictionary

{
WeaponType = “Sword”,
Price = 120,
Damage = 200,
Speed = 20
}

And now lets say you want to send WeaponType only. Some beginners developers may send all the table values, when 3 of the values it has are not necessary.

Imagine a CFrame and you need to send only the position to the client. Why send the entire CFrame when you can send CFrame.Position?

You should not be sending CFrame data like that unless you are using one of the modules mentioned, preferably use one buffer and store the position numbers in i16-i32 values if necessary.

Unreliable remote events

One variant of remote events that the server allows itself to ignore in order to save system resources if necessary. Most of the time you wont need this, but in some specific ocasions it may be useful. Remember, it has a 1000 bytes limit! Remote events do not have a size hard-limit!

Lets put a random example; lets say you wanna send a event for players devices to make X fire particles emit in a location. In this case, its better to use unreliable remote events, as it does not matter that much if the server decides to ignore and cancel the event.

Server simulates, client creates the visuals

Lets say you have a shooter game where the bullets are physical objects (plasma guns, for example). The server does not need to have the physical objects, it just needs to know where the bullet is, the direction, speed and origin.

Taking this in mind, you can just make the bullets objects appear phisically for players, and destroy them if the server detects they hit something. That way, you save the data of replicating the objects from the server to the client. It can really help when you have a lot of bullets

Its not only limited to this. Particles? RTS 3D Units?

If there is no need to have something physical on the server, dont do it. Let the clients make a replication themselves. Your server network performance will thank you.

Checking bandwith usage

Simple, using developer console (open it in the menu, typing /console in the Roblox default chat or pressing F9). To check the bandwith usage in the developer console, go to ServerStats, and check for the property called “Total Data KB/s”.

How do I know if there is too much bandwith usage / bad network performance?

Generally, if Total Data KB/s is over 100, you will probably need to optimize a few

--------------------------------------------------------------------------

Extra

Remember, compressing data will not do much for your game if the code is unoptimized and the game runs like shit because of it. Make sure to optimize your code!

Things like spawning a lot of moving objects in the server will lag the game due to the amount of data about the objects needing to be replicated to the clients.

---------------------------------------------------------------------------

End

Thank you for reaching the end of this guide. I may add more details in the future! If you wish to support me, you can do so by joining this game and donating: Wolo - Donation Place - Roblox

Other posts of mine:

13 Likes

A byte has 8 bits :face_with_monocle:

And storing 64 bits requires 8 bytes, 64/8, this is why f64s take up 8 bytes

Oh, terrible mistake by me, didnt notice :rofl:

Thank you for the correction!

1 Like

Awesome, i didnt ever thing about network perfomance before until this moment, thanks you!

Glad it helped you!

It may not be necessary to optimize a lot on network performance for simple things like tyccoons, but doing it for games like RTS ones surely help.

How do i make parenting 1k+ objects/s to workspace (serversided) use less bandwith? the client sends ~1000 requests to server > only 20kb/s.. then it receives like 400kb/s from the parenting currently im mitigating this by making the parents max do 250/s but i dont actually want that, the instance im parenting is already as optimized as can be and yes its required to be parented for functionality

First: can the objects be parented client-side only while only storing data in the server? This would almost completely eliminate all bandwith usage from this.

Second: do all the objects need to be parented at the same time, or can some of them be saved and then parent them when necessary?

Third: can you union / turn to mesh groups of objects to turn them into a single one? If you managed to join, for example, 20 objects into a single one per group (1000 / 20 = 50) this would also save a lot of bandwith.

If you can show images of what you need to parent I could probably give more tips based on your specific case

I have a tree / foliage etc planting system and basically everything is currently handled server side, placing, destroying, interacting etc and needs to be shown to all clients so its close to impossible to make it client sided without making an entire new game

they all need to get replicated as fast as possible thats why the current queue limiter of 250/s is not ideal stuff like tweening etc are all already client sided its basically just the parenting now

You can make the planting system representation client-sided, and only store data server-side.

Example:

Server

{
Type: “Tree”,
Location: XXX,
Size: XXX,
Owner: XXX
}

Client
Represents, creates models and modify it based on what the server tells it from events

You would have to follow the idea of server handles and stores, client represents. I will not lie, it will still require a lot of code writing. But if the previous ideas do not work in your case, I do no think you have a lot of options then

Another idea that came to my mind today; you can also “fake” the plants in the server. If you wanted to put a tree, you would put a single block part of representation for it in the server, and then tell the client to replace that part with the tree model. This way you would also save a lot of bandwith, not as much as faking it ocmpletley with just data on the server, but still a lot.

1 Like

For optimizing bandwith in terms of events would something like this be simple? Jolt | A high-performance, type-safe, and developer-friendly networking library for Roblox - #23 by ToriumSlurs I am a beginner dev when it comes to optimizing bandwith and this module looks like something I can handle rn

is there more tips like that for saving bandwidth?

Bandwidth optimization isn’t really matter if you don’t use “too much” data.
Some games don’t need one, even for big games.

But for beginner, networking library is good. But you don’t need one if you know how to use buffers.

Also if you want really heavily reduce bandwidth, you should try many diffirent compression methods , like delta encoding , elias gamma (a type of variable length encoder) or the other type of varint, scalar quantization. But not really recommended for a beginner.

As @vantoanvh said, not every game needs bandwith optimization. If you are a beginner developer, the games you would be making are probably very small and their data consumption should not be significant.

Networking libraries are good to simplify the optimization process, though I prefer to make my own libraries. When you start making big games that do require bandwith optimization you can use those libraries to speed up development.

I do not relaly have more tips to optimize network performance / saving bandwith, at least right now

1 Like

My latest project uses like 60 to 70 Bandwidth every second in my latest project and it is lagging players

Whats your game? Can you send a link? DO you know which parts / events of the game are causing the lag?

No I haven’t figured that out yet Game Link: https://www.roblox.com/games/124750283427406/Baldis-Basics-Hide-and-Seek-V2