This article is written on 21/8/2023. It has been last updated on 19/9/2023.
Contents have been vetted to be accurate up till the date of the update as mentioned above.
This guide was written for beginner levels. For a summary, see the bolded text for each section. For feedback, feel free to post it in the comments below.
The Client-Server Model:
In every Roblox experience, there are two entities - the client and the server.
You play Roblox games on a client that you install on your PC, while the server is what Roblox maintains on their backend to make sure the game functions for all the clients it is connected to.
Understanding this model is the basis to any netcode you may be writing, in the form of
But what happens when this model is abused by developers?
To illustrate the don'ts of writing netcode, let's set up a problem, come up with a few potential solutions, and iteratively improve on them if necessary.
Imagine you were a scripter for a simulator game, and you were tasked with this:
Design a system where players collect coins, upon which the collected coin is deleted. Also reflect the amount of coins gotten in leaderstats.
What are some of the possible approaches you can make, and what are the problems with them?
Detect when the player touches a coin, delete the coin, and update leaderstats, ONLY on the client.
If you have any experience with Remotes, the problem with this approach becomes immediately obvious:
Changes made on the client do not replicate to the server without the use of a remote.
This means that the server will not even catch that your leaderstats have been updated, so to everyone else, it'll be as though you had never collected a coin at all.
If this is the approach you are using (and I hope no one is), you should probably finish this guide before you do anything else related to netcode.
Detect when the player touches a coin on the client, and tell the server using a remote, which will then delete the coin and update leaderstats.
While the issue of collections not being reflected to the server (and in extension, the other clients) is now resolved, there is now a just as pressing problem:
Exploiters can change the data sent through remotes, and can fire them at will.
If you are using a remote to tell the server that your client has received a coin, an exploiter can fire that remote extremely often (think hundreds). That's hundreds of coins that your player has illegally gotten, which racks up extremely quickly into the millions.
We can do better.
Detect when the player touches a coin, delete the coin, and update leaderstats, ALL on the server.
Great, our changes are being replicated to all the clients, so any coin collection made by a player can be considered valid. But now there's a small problem:
When a player touches a coin on his screen, it is taking a while for it to be deleted.
Due to ping, any changes made on a server will take a short moment before a client can see them on their screen. What if we want our system to feel fluid and responsive, such that a player gets instant feedback when he collects a coin?
Detect when the player touches a coin both on the server and client, where the server updates leaderstats, while the client deletes the coin for itself.
There, the client can now see effects instantly when it collects a coin, while only the server is handling the leaderstats, ensuring security.
...and then we immediately run into another problem:
The other clients can still see and collect coins on their screen, and is recognized by the server as valid.
Small oversight, we can fix that quickly.
Detect when the player touches a coin both on the server and client, where the server updates leaderstats and deletes the coin, while the client also deletes the coin for itself.
There we go! This works!
The great solution splits different code actions into 2 categories: the visuals, and the data.
These general rules of thumb are important if you are handling networking, as these will help you write secure game logic while still ensuring a smooth gameplay experience for your players.