A Scripture's Guide To Scripting

There is no doubt that Scripting is one of the most valuable aspect in Successful Games and arguably one of the most important skill to learn in Game Development.

In this Thread I would like to share my experience, guides, tips & tricks from my years of Scripting; I have freelance, collaborate with Developers, teach new scriptures and currently teaming up with a Family.



Naming Variables

I've seen a lot of bad code with terrible Variable Names

Here are a few Examples;

local myCharacter

local myHumanoid

local myPlayer

There is no reason to use “my” it’s very unnecessary and adds 2 extra characters but that I can deal with that, it’s not a huge problem.

What really upsets me are poorly named Variables

sp=script.Parent
local chr=sp.Parent
local t=chr:FindFirstChild("Torso")
local h=chr:FindFirstChild("Humanoid")

local p = Instance.new("Part");
local w = Instance.new("Weld", p);
local f = Instance.new("Fire",p);

No one not even the Scripture would know what “p, w, f, h, t, chr” means without context!
There is nothing wrong with compressing and making your code short but please keep it’s integrity.
__

So how can I improve my code's readability and integrity?

Put some thought into naming your Variables, make sure it explains itself well without context

The same rule applies to Functions, Arguments and Parameters

-- VARIABLES

local Color3_New = Color3.new

local UDim2_New = UDim2.new

local CFrame_New = CFrame.new

-- FUNCTIONS

local function GetCharacter(Part)
end

local function RecalculateHipHeight(Character)
end

local function ScaleModel(Model, Scale)
end

local function CharacterAdded(AddedCha)
end

Guides recommended by readers:

Roblox Lua Style guide
Lua Style Guide
Lua Rocks Guide

Disclaimer : Not everyone has to do this, it’s a personal style

I usually do Name_Func and Name_Event to give it an extra identifier


Indenting Code

Not indenting code is a sin

Please don’t to this

local function Name_Func()
if true and true or true and not true then
while wait() do
do
repeat wait() until true
for i = 1, 10 do
local Table = {
Name = "John",
Age = 10,
Gender = "Male",
Job = "Banker",
}
end
return
end
break
end
end
end

Do this

local function Name_Func()
	if true and true or true and not true then
		while wait() do
			do
				repeat wait() until true
				for i = 1, 10 do
					local Table = {
						Name = "John",
						Age = 10,
						Gender = "Male",
						Job = "Banker",
					}
				end
				return
			end
			break
		end
	end
end

__

Disclaimer : Not everyone has to do this, it’s a personal style

Something that I do is Indenting based on Hierarchy

-- SERVICES
local PlayerS = game:GetService('Players')
	local plr = PlayerS.LocalPlayer
		local Backpack = plr:WaitForChild('Backpack')
		local Cha = plr.Character or plr.CharacterAdded:Wait()
			local Hum = Cha:WaitForChild('Humanoid')
				local RootPart = Hum.RootPart
		local Mouse = plr:GetMouse()

Creating Sections

An easy way to make your code easier to read is by creating Sections
-- SERVICES

-- MODULES

-- VARIABLES

-- TABLES --

-- META TABLES & META METHODS --

-- FUNCTIONS

-- SCRIPTS

--[|Remote Events|]--

--[|Remote Functions|]--

-- LOOPS

Tables

Tables are very versatile, powerful and used everywhere

Tables have many forms, it can be an Array, a Dictionary, a Mixed-Table, or even a Metatable.

Learning and Understanding Tables is massively beneficial because not only that you can make certain Services work better but sometimes it requires related knowledge, notably;

DataStoreService, RemoteEvent / RemoteFunction, MarketplaceService, UserInputService, TeleportService, and many many more.

This should help you understand how Tables work by using print() and you reading the output

It also allows you to write less code for the same if not better results


Use Modules

Having too many Scripts in your game is a sin

You have at least one Script for each Object, but don't worry I've done this too when I first started Scripting

The problem of having too many Scripts are;

  • When you want to change a behavior of Game Objects you have to change every Script in them

  • It’s confusing while debugging

  • It might impact performance

The main idea here is you should not have too many BaseScripts

__

Fixing this is simple; learn how Tables and Modules work, have one Main Script each for the Client and Server then create a Module for features that are related to each other, for example;

I have one ServerScript, one ClientScript

I have a ModuleScript for MarketplaceService, PlayersData, RemoteInstance and other stuff.

  • This is handy because when I finish Scripting a Feature I don’t have to look at it again until it’s necessary, code is easier to find, more organized, more readable and easier to debug.

Not using Operators

Utilizing Operators will shorten your code and increase readability

I have seen many Scriptures do this

if FirstBool == true then
	if SecondBool == false then
		
	end
end

But you can do this instead

if FirstBool and not SecondBool then

end
  • Only use “==” and “~=” when you want precision

  • You can use “and”, “or” instead of creating unnecessary Nested If Statements

__

MusicBtn.Color3 = On and Green or Red
  • Use Ternary Operator instead of creating an If Statements

Understanding RemoteEvents and RemoteFunctions

Before using Remote Instances you must have an understanding of Server - Client Model, however a simple way I like to put it is

  • RemoteEvents Fires an Event on the Server to run code via the Client and vice versa.
  • RemoteFunctions Calls a Function on the Server to run code via the Client and vice versa and returns a value to the Invoker.

If you still have trouble understanding RemoteEvents & RemoteFunctions you can play around with BindableEvents & BindableFunctions.


Dealing With Exploits

Most of the time your game is Exploitable because of poorly written code

In a FilteringEnabled game the only thing that is Exploitable are poorly written code implemented into RemoteEvents and RemoteFunctions, if you don’t give the Client power and always do Sanity checks on the Server there is nothing you’ll have to worry about.

It’s been said many times “Never Trust The Client!”


Stop Using JSONEncode Wrong

I have seen a lot people use JSONEncode to send a Table to DataStoreService, MessagingService and RemoteEvent / RemoteFunction

The truth is you don’t have to, Roblox automatically does this so what you are doing is redundant and slow.

You only have to use it for GetAsync, PostAsync and RequestAsync


Minimizing Lag

You need to optimize your code because not all players have a modernized state of the art device, some might be using a Toaster to play your game.

Do not fall into the rabbit hole, do not over optimize your code, don’t be a perfectionist be a person that gets things done.

A lot of people will say “If you don’t have a Performance problem don’t try to fix it, don’t optimize your code”

They might be right but I am not one of them, I rather prevent it from happening than fixing it later especially when you have a FrontPage game, but minimizing your Script Activity / Usage will increase Performance only when done right, however keep in mind that Latency is something you can’t avoid but can minimize, however this is often times not caused by your code.

Recommended by Readers:
You can also use the MicroProfiler to analyze and debug performance problems.


Using Loops Instead Of Events

Only use Loops when they are necessary, most of the time you can use an Event


Debugging

  • Use print() print() will always tell the truth
  • Read the Output Window

Recommended by Readers:
You can also use the Lua Debugger to inspect your code more indepthly.



Thanks For Reading!

Thank you for reading, here’s my gift to you Simple Scripts For Beginners

If you have any questions I’ll do my best to answer it, and please let me know if you have any issues.

Have fun Developing - Sincerely RuizuKun_Dev

70 Likes

Recently I’ve used the microprofiler a lot more as it’s very difficult to debug memory leaks and other issues in codebases that are completely based on module scripts. I would probably add information on the microprofiler underneath the “print to debug” section as it goes with debugging.

3 Likes

The names you provide as an example don’t really follow any variable naming conventions that I’ve seen; I think as long as it’s understandable it doesn’t need to be verbose. It’s understood GetCharacter is a function from its name alone, no need to append _Func for example. Instead of _Event you could also just do OnCharacterAdded. I guess in general it looks funky since it seems to be a mix of PascalCase and underscores too.

Nothing inherently wrong with this, it actually applies to having too many modules too.

9 Likes

I agree, those are my naming convention shown as examples.
Nobody has to do what I do aside from the Standardize practices, it’s a Guide after all.

Correct me if I am wrong but I don’t think Lua has a naming convention unlike C#


I also agree but the idea is having less Scripts including Modules are better in most cases as I have specify that one might have a Script for each Game Object which is terrible practice, thus implying less is more simple.

2 Likes

Not sure I agree with indenting based on hierarchy; it’s not a standard industry practice and feels very unneccessary. I see what you’re trying to do by indenting related variables, but that benefit in readability feels very marginal at best, while confusing other people looking at your code. I’d stick to indenting only where it’s traditionally used.

Concerning print debugging, I think you should talk about using the built-in script debugger as well. Print debugging has its uses (and is better than not debugging at all), but the script debugger in Studio is much more powerful and can help you debug more efficiently.

Everything else in your post looks spot on for beginning scripters. Keep it up!

7 Likes

This is unnecessarily verbose and obnoxious to read. charAdded, playerSpawned or onSpawn are both shorter and mean basically the same thing. Sticking _Event and _Func at the end of your functions doesn’t improve readability at all.

3 Likes

There’s nothing official, but you should try to stick to PascalCase or snake_case and not a weird mix. Following the Naming section at lua-users is generally what I’ve seen people do.

2 Likes

Somewhere, I have found this guide:
https://roblox.github.io/lua-style-guide/

I remember this was posted elsewhere sometime far back. I don’t remember the topic but at least I remember there were guides.

3 Likes

In the debug library there’s a function GetUpvalues or something.

Great article and a must read for all new scripters, especially the sections about laying out code and having too many scripts!

2 Likes

No, this is a trap. Your code should not need sections.

If you feel the need to split your code off into sections, either your variables/functions aren’t named properly for someone to understand just from reading those names, or your script has become too large/encompassing and you need to start splitting it off into modules.

This variable naming style is a little frightening – I suggest sticking to either camelCase or PascalCase or underscore_case, and not switching between camelCase and WhateverThis_Is or thisVariant_YouUse.

Putting “Func” at the end of something that is a function seems unnecessary. Your function is called “GetCharacter” so that should allow the programmer to understand just from the name that it is a function they can call.

6 Likes

I presume you meant “Scripter” and not “Scripture” :stuck_out_tongue:
I don’t personally agree with everything that you’re stating here.


Variables

There is no reason not to use “my” in the names, it’s up to the scripters themselves to determine and figure out how to solve this problem at a larger scale. There is nothing wrong in using “myCharacter”, “myHumanoid” and “myPlayer” in my own opinion, other than maybe it should be in a table with all the local player’s stuff!

BUT, I totally agree that names should make sense, and I believe people should read this article on how to properly create variable names. It does a better job explaining this than I do; Writing Variable — Informative, Descriptive & Elegant | by Kevin Hobert | DataDrivenInvestor

Just to add onto it, stick to one way of writing. If you start mixing you will be confused later on. Find your own liking of how to write variable names. For example, some people make constant variables CAPITALIZED:

local ALL_ANIMATIONS = {},

Others don’t. Find yourself a good way of writing code, find a good / recommended style practice, so you can be consistent with your code and mind.


Commenting

Oh yeah, comments :sunglasses:.

Comments are underused and comments are overused.

There are people that have never used comments in their entire lives and are probably not sure about:

  • what to comment
  • why they should write comments
  • how to properly put comments in their code

There are also the ones who write more comments than code, and the ones who “over-comment” code, basically telling exactly what some piece of code does even if it’s self-explanatory.

Comments are pretty much documentation for your script, to help you(r future self) and your colleagues to understand what your brain actually tried to do 2 months ago.

I could write detailed about this, but hey, why re-invent the wheel the post?


Indenting

What is indenting?
Indenting is pretty much about adding space to your code to… , well, to give yourself some space when reading your own code. Indenting makes your code look more professional and less like a mess, and makes it easier for you to read.

How do I indent?
Fortunately, it’s very easy, it’s as simple as hitting “Tab” and “Space” and “Enter” on your keyboard.

Look at these two samples, which one of them would you not read/enjoy reading.

1

2

Number 2 is 6 lines more, but to me, that’s 6 more lines of extra pleasure.

Interested? Check out: https://blog.programminghub.io/blog/2017/06/07/importance-indentation-programming/

Modular coding, splitting code up!

My story:

I was creating a Discord bot when I was learning JavaScript, with many features and commands. I was very new to the language, and I smashed everything into the same script. There were 5000 lines of code, and I had to create sections within my code because of all the code, and when I had to change something, I had to scroll through that ugly mess. I actually tried to remember where each and every function were so I could easily just enter the line number next time. The result? The bot was never made! A month later, I was introduced to MODULES. My LIFE SAVIOR, I would have quit programming if it wasn’t for this. I knew while writing in the huge script, that 5000 lines is bad and wrong, but I didn’t know how to fix it. Previously on Roblox I had a separate script for everything that happened, so yeah. Mess 100%, just like this block of text about indentation :wink:

As with comments, people abuse modules too!
You. Don’t. Have. To. Create. A. New. ModuleScript. For. Every. Function. You. Have.
Just as I don’t have to write like the above, you don’t need a module for every function.

ModuleScripts are a way to split your code logic into more, but smaller pieces (or chunks) of code.
They are (often) supposed to be independent, but, there are some exceptions!!

Your main scripts are supposed to call the ModuleScript so it can do its stuff, if the ModuleScript the main script originally called, depended on another module, that depended on another module, that depended on another module, failed, well, confusion happens.

Modules are a way to share the functions between several scripts. Imagine you had a function called “AddNumbers” that was only about adding all the numbers you provided it, you could put it into a module, with other math functions. Then, when another script needs this function, it simply requires the module and calls the function.

Alternatively, just copy the entire function into every script that needs it, so that when you notice there is a bug in the code, you only have to update the same code 13 times because you put it in 13 different places. (I’m joking, please don’t do this. This is why you would want to use modules :frowning: )

Here are two posts you can check out (they are about other languages, but the concept and goal is the same):

Operators

Using ternary operators or “==” is an entirely personal opinion, mostly.

Personally, I like using “==” and “=~” when I can, because then I am sure what type, or value I am matching it against, which, for me, will return in easier debugging (and readability) if needed in the future!

Ternary operators can also be used, but please, use them with caution. Don’t sacrifice simplicity, readability, and maintainability only because you desire less code and want to make it look cooler or complex. Remember, less code does not always mean it will make a huge enough impact to make it worth it.

Security

Well, secure your game! I can’t say much about the coding logic, but I can tell that you don’t trust the client. Have you heard the saying “The customer is always right” ? Well, in pretty much all cases it’s WRONG. This applies both to games and in real life. Customers are wrong, and your players are wrong. Your server is right, as long as you make it that way.

The clients should never command your server to do something, they should ask the server politely to do something. If you make the client command the server like this: “Give me 1,000,000 money NOW”, you’re most likely implementing it that way too. If you make the client ask “Can I please get 1,000,000 money?”, you will probably be implementing a check to see if the player should get that money or not.

As a Roblox player, please don’t allow players to do basic exploiting such as teleportation and speed increase/decrease. It ruins the experience :frowning:

Debugging

If you have a function that needs speed, print should be avoided. print is sync and slows down the code (especially in loops). Use a third-party service like sentry.io to save logs. Put logs into a table and report it every X minutes. Remember that bugs that are not reported/logged don’t exist (for you). Without logs, you are blind and don’t know where to look (or maybe you do).

I think that’s it.
If you have the time, I recommend checking out a video on how to hide the lag from your players in an “I shot you first” context.

5 Likes

I think its fair to say everybody has their own style of scripting and nobody is ever going to agree on a set format. its just finding what is ‘readable’ to other devs, efficient and easy to debug.

3 Likes

This tutorial is a good start but I have some notes:

  • Your bad examples of variable names aren’t really bad. I’d change them to actual bad examples such as local A = Player.Character and say that variable names should display what the variable actually is.
  • You mean scripter not scripture
  • Adding _Event or _Func seems like a bad practice. Are you not able to figure out your function is a function from the the function before your function? (That was annoying to type and read).
1 Like

I like the tips you’ve given that novice programmers would find really useful, but please consider changing the title from ‘scripture’ to ‘scripter’.

2 Likes

This guide generally reflects my style, but there are a couple things I prefer to do which would be considered bad:

  • I prefer to align curly braces instead of inlining them, it’s something I inherited from C#
  • Sometimes I use vertical alignment because it kills my OCD if I don’t.
1 Like

Thank you everyone for your feedback, I will act accordingly to improve my Thread.


Recently added 3 new sections;

  • Dealing With Exploits
  • Understanding RemoteEvents & RemoteFunctions
  • Minimizing Lag

__

Added recommended content to certain sections.
Added more context to certain sections to improve conciseness.

1 Like

This is awesome. I recommend all new scripters read this post. Even I learned something! I think it’s hard for beginner programmers to pick up certain habits needed to progress so giving them something like this is awesome. Good work!

2 Likes

That is also fair, but imagine you have 3 scripters on the team. If you don’t have some kind of commonly accepted structure and layout of your code, they will end up being confused and/or annoyed.

If I were hired by someone to work with another scripter, I would have quit the moment I saw this
image
No offense you OP, it’s just that I don’t like the indentation of the code, nor the variable naming, which, ironically is listed in this topic as well and you didn’t follow your own rules in this topic.

Who knows, maybe in the future someone creates a great set of rules to follow for Lua :thinking:

3 Likes