How Do You Guys Keep Your Code Neat?

I section off different parts of the script like shown below, and have a space between different “groups” of variables if there are a lot of them. Also I use a lot of new lines to separate different parts of code

--// Services

local Players = game:GetService('Players')
local ReplicatedStorage = game:GetService('ReplicatedStorage')
local Teams = game:GetService("Teams")


--// Variables

local Maps = workspace.Maps --folder of maps
local intermissionlocation = workspace.IntermissionLocation

local Values = ReplicatedStorage:WaitForChild("Values")
local TimeLeft = Values.RoundTime -- A timer for a gui to reference to

local Red = Teams.Sentinels
local Blue = Teams.Mavericks


--// Constants

local INTERMISSION_TIME = 5
local ROUND_TIME = 5
6 Likes

I group the lines in my script into 5 different sections.
A bad example script:

--| Services & Modules
local CS = game:GetService("CollectionService")

--| Variables
local damage = 20

--| Functions
local function touched(hit)
    local hum = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
    if not hum then return end -- guard clauses on top

    hum:TakeDamage(damage)
end

--| Events
for _, v in CS:GetTagged("KillBrick") do
    v.Touched:Connect(touched)
end

--| Start
print("running or smth idk")
3 Likes
  1. First, by enforcing a style across your codebase (such as the Roblox Lua Style guide)

  2. Secondly, take @ Orbular3’s advice and detail each code section with a comment.

-- Services

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Teams = game:GetService("Teams")

-- Instances
local Values = ReplicatedStorage:WaitForChild("Values")
local Maps = workspace.Maps
local TopbarText = Values.TopbarText

-- local variables
local maps = table.freeze(Maps:GetChildren())

-- constants
local INTERMISSION_DURATION = 5
local ROUND_DURATION = 5

local function distributeTeams()
    local players = Players:GetPlayers()

    for i, player in ipairs(players) do
        if i >= (#players / 2) then
            player.Team = Teams.Mavericks
        else
            player.Team = Teams.Sentinels
        end
	end
end

local function intermission()
    for second = INTERMISSION_DURATION, 0, -1 do
		for _, player in ipairs(Players:GetPlayers()) do
			player.Team = Teams.Intermission
		end

		task.wait(1)
		TopbarText.Value = "Intermission: " .. second
	end
end

local function chooseRandomMap()
    return maps[math.random(1, #maps)]
end

-- game loop
while true do
    intermission()

    local map = chooseRandomMap()
	print(map.Name .. " has been chosen")

    distributeTeams()
	
	for timeRemaining = ROUND_DURATION, 0, -1 do -- job of this script is to control the round 
		TimeLeft.Value = "Time Remaining: " ..timeRemaining

        ...
        
        task.wait(1)
	end
end
4 Likes

If you have a lot of scripts, I would recommend to put comment lines at the top that describe the start lines of every function (this is very useful for longgggg scripts). Another thing is always, always name your scripts to their function. It will make your life so much easier.

3 Likes

Like other people said, you can organize your code by separating lines into multiple different sections which make you script easier to read.

Also, your feeling about the code being sloppy is probably because of the overuse of for_do.
Here is an exemple of your code reworked to be more linear and easier readable:

--[[ Roblox Services ]]--
local PlayerService = game:GetService("Players")
local TeamService = game:GetService("Teams")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

--[[ Instances Variables ]]--
local intermissionlocation = workspace:WaitForChild("IntermissionLocation")
local Maps = workspace:WaitForChild("Maps") --folder of maps
local Values = ReplicatedStorage:WaitForChild("Values")

local TimeLeft = Values.RoundTime -- A timer for a gui to reference to
local InRound = Values.InRound -- not used in the script

local Red = TeamService.Sentinels
local Blue = TeamService.Mavericks

--[[ Settings Variables ]]--
local IntermissionTime = 5
local RoundTime = 5

local CurrentTime = 5
local CurrentState = "Intermission"
local CurrentInfo = "Intermission: "

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

--[[ Local Functions ]]--
local function SwitchTeams()
	for _, Player in pairs(PlayerService:GetChildren()) do
		if CurrentState == "Intermission" then
			Player.Team = TeamService.Intermission
		elseif CurrentState == "Round" and #Red:GetPlayers() > #Blue:GetPlayers() then
			Player.Team = Blue
		elseif CurrentState == "Round" and #Blue:GetPlayers() > #Red:GetPlayers() then
			Player.team = Red
		elseif CurrentState == "Round" and #Blue:GetPlayers() == #Red:GetPlayers() then
			local Teams = {Red, Blue}
			local RandomTeam = Teams[math.random(1, #Teams)]
			Player.Team = RandomTeam
		end
	end
end

local function MapSelection()
	local ChosenMap = Maps:GetChildren()[math.random(1,#Maps:GetChildren())]
	print(ChosenMap.Name.." Chosen")
end

local function SwitchState(NewTimer, NewState, NewInfo)
	CurrentTime = NewTimer
	CurrentState = NewState
	CurrentInfo = NewInfo
end

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

--[[ Rounds Setup ]]--
while task.wait(1) do
	if CurrentTime > 0 then
		CurrentTime -= 1
		TimeLeft.Value = CurrentInfo.. CurrentTime
	elseif CurrentTime <= 0 and CurrentState == "Intermission" then -- Entering to Round time		
		SwitchState(RoundTime, "Round", "Time Remaining: ")
		SwitchTeams()
		MapSelection()
	elseif CurrentTime <= 0 and CurrentState == "Round" then -- Entering to intermission time
		SwitchState(IntermissionTime, "Intermission", "Intermission: ")
		SwitchTeams()
	end
end
3 Likes

Along with setting state types as enumerations, like:

-- // example states
local states = {}
states.starting = "Starting"
states.intermission = "Intermission"
states.ended = "Finished"

-- //
local function foo(state)
    if states.starting == state then -- // basically the idea
    end
end

foo(states.ended)

This would allow other developers to come in and know where all state types are and can easily be type checked.

1 Like

Here’s a good video that explains why less is more when it comes to comments

Sections of code can be separated with one or multiple line breaks. Code should be self-explanatory. Descriptive variable names make most comments redundant. This includes variable comment blocks – you should be able to determine the type of variables by reading them.

As long as you don’t use wacky indentation for code blocks, make sure to add empty lines around function blocks, and use descriptive names for variables, I think it’s hard to write unreadable code. Maybe I’ve been reading code for too long since I work as a software developer now, so it’s just like picking up and reading a random page in a book.

just use stylua its so much easeier

1 Like

I try to keep my code neat by being consistent with things such as variable/function naming, grouping up variables based on what value they hold instead of just clumping them up all together at once, adding the occasional comment for sections of code that I may forget what it does if I ever come back to it later. And for those wondering, I use camelCase (used to be a snake_case user for the longest time but switched because of Unity and C#. Also because its less characters and easier to type out lol)

I use a plugin I made which automatically formats my scripts

Don’t write any comments besides headers that have the author(s) and a general description. If you need to write comments, you can easily just change variable names to reflect what you want the reader of the code to know. Comments can become outdated. (You know the resource is worth looking at when two different people recommend it, lol. Someone beat me to it!)

When in doubt, use a line break.

Before:

local IntermissionTime = 5
local RoundTime = 5
local Maps = workspace.Maps --folder of maps
local intermissionlocation = workspace.IntermissionLocation
local Values = game:GetService("ReplicatedStorage"):WaitForChild("Values")
local Teams = game:GetService("Teams")
local Red = Teams.Sentinels
local Blue = Teams.Mavericks
local TimeLeft = Values.RoundTime -- A timer for a gui to reference to
local InRound = Values.InRound -- not used in the script
local Players = game.Players

After:

local PlayersService = game:GetService("Players")
local TeamsService = game:GetService("Teams")
local WorkspaceService = game:GetService("Workspace")

local maps = WorkspaceService.Maps --folder of maps

local intermissionTime = 5
local intermissionLocation = WorkspaceService.IntermissionLocation
local timeLeft = Values.RoundTime -- A timer for a gui to reference to
local inRound = Values.InRound -- not used in the script
local roundTime = 5

local values = game:GetService("ReplicatedStorage"):WaitForChild("Values")
local sentinelTeam = TeamsService.Sentinels
local maverickTeam = TeamsService.Mavericks

Organize with consistency as well as in the order of when it’d usually be used. Also if they’re in a group, they should be ordered alphabetically. I didn’t order them alphabetically because of time but I do in my scripts.

No don’t do this. pascalCase + writing good variable names is 10x more consistent and cleaner looking than this. As someone unfamiliar with your code, “subint” and even “repstr” would force me to review your code further to see what they mean. It’s not worth it.

A lot of other people have covered breaking your script into chunks, but I thought it wouldn’t hurt to share how I do it. I try to make chunks in the following order: services, modules, single functions from modules, localized global function, instances, custom enums, data variables (tables included), functions, connections, loose code that justs runs. I do what I can to keep my variable naming consistent across my scripts, partially so I can copy and paste lines with ease. I also do what I can to give my variables clear names.

--// Services
local ts = game:GetService("TweenService")
local ds = game:getService("Debris")
local Teams = game:GetService("Teams")

--// Modules
local GameFunctions = require(game.ServerStorage.GameModules.GameFunctions)
local FacilityControl = require(game.ServerStorage.GameModules.FacilityControl)

--// Single functions from modules
local AttackHuman = require(game.ServerStorage.GameModules.CombatFunctions.CombatFunctions).AttackHuman

--// Localized functions
local wait = task.wait
local tbup = table.unpack

--// Instances
local Electrical = workspace.GameMap.Electrical.PowerSystem
local Generators = Electrical.Generators
local Controls = Electrical.Controls

--// Custom enums
local PowerStates = {
	On = 1,
	Off = 2,
	Transition = 3
}

--// Data variables
local Data = {
    PressCount = 0,
    PowerState = PowerStates.Off
}

local ButtonDeb = false

--// Functions
local function _1984(plr)
    plr:Kick("RED SUN")
end

--// Connections
game.Players.PlayerAdded:Connect(_1984)

--// Loose code
print("Hello there.")

I’m not a hardliner about following the above patterns—none of my scripts follow them perfectly nor can they at times—but they are my general guidelines for keeping my scripts organized and tidy.

In my longer scripts, I frequently split sections of code with separators made of a lot of dashes. One section could be all the variables, another for BindableEvent connections, and yet another for ClickDetector connections. How exactly I do it changes with each script and where I find them helpful.

I hate making scripts longer than they need to be, but I will sometimes trade line count reductions for readability by spliting extremely long if statements and tween across multiple lines. This isn’t the best example, but it’s an adequate demonstration:

T1 = ts:Create(
	Bar.MovingChargeBar,
	TweenInfo.new(0.35,Enum.EasingStyle.Linear,Enum.EasingDirection.Out,-1,true,0),
	{BackgroundColor3 = Color3.fromRGB(223,0,0)})
T2 = ts:Create(
	Bar,
	TweenInfo.new(0.35,Enum.EasingStyle.Linear,Enum.EasingDirection.Out,-1,true,0),
	{BackgroundColor3 = Color3.fromRGB(89,0,0)})
1 Like

yes so its 10x easier for hackers to change it :skull:

1 Like

Hey Disastr0WasTaken!! I’m gonna send my honest opinion on this topic!!

I feel that keeping code neat is really important prepending on the script and how often you’re gonna edit the code.

Example 1:
If you are making a leaderstats script, you’re prob not gonna need to make it super neat, but also not super messy. Code needs to be readable. And also editable. Leaderstats sometimes need to be edited every so often to change small changes, or to change data storage variables. Which is why it should be at least split into variables for the sake of easy maintenance and your sanity!!

Example 2:
Let’s say you have a config script, or a UI script. Those need to be changed very often for different in-game things and data. If you have them unorganized have fun losing your sanity while trying to organize it.

I honestly just organize the code by splitting stuff between lines, and using comments every so often. No matter the script. But that’s just me and if I am in the mood too lol. Happy Dev! :heart: ^^

Edit 1: I also forgot to state. It’s very smart to keep your variable naming, but don’t have too many comments. This YouTube video States a decent reason why also just realized the YouTube link was already posted lol

3 Likes

i create an entire game and then throw away all the code i wrote and write the whole game again

2 Likes

I guess with me , there’s not much to see

2 Likes

That’s not so true, because the code could be on the server instead of in the client, so there would be no damage to it.

1 Like

I follow my own format, but you can find stuff like this:
That might help you!

Also, using modules will help you big time.
And another thing is I like to separate Services, variables, and code.

– SERVICES

– VARIABLES

– CODE

And I don’t recommend spending all ur time making fancy annotations, as coding is pretty much 10% Writing the code, 90% figuring out why the code doesn’t work and updating the code.