Localize as many functions and variables as possible. Lua can read them faster
myVariable =false-- Don't use thislocal myVariable =false-- Use thisfunctionsomeFunction() -- Don't use thisprint('Im a global function!')endlocalfunctionsomeFunction() -- Use thisprint('Im a local function!')end
Instead of using table.insert use tableName[#tableName+1] = data
functionsomeFunction()local table = {}table.insert(table, {}) -- Don't use this table[table+1] = {} -- Use thisend
Instead of using if something ~= nil use if something then. This method checks for nil and/or false at the same time
functionsomeFunction()local bool =nilif bool ~=nilthen-- Don't use thisprint('bool was not nil but also could be false!')endif bool then-- Use thisprint('bool was neither nil or false!')endend
If you are creating a function or an event, make it so that it can be used in different scenarios with different variables. Keep it universal basically
localfunctionsomeFunction(param1,param2,param3)print('Im a function that accepts 3 parameters which allows for multiple conditions!')if param1 =='something' thenprint('I met condition number one!')elseif param2 =='somethingelse' thenprint('I met condition number two!')elseif param3 =='somethingelsemore' thenprint('I met condition number three!')endendRegisterNetEvent('someEvent', function(param1,param2,param3)print('Im an event that accepts 3 parameters which allows for multiple conditions!')if param1 =='something' thenprint('I met condition number one!')elseif param2 =='somethingelse' thenprint('I met condition number two!')elseif param3 =='somethingelsemore' thenprint('I met condition number three!')endend)
When writing code use what's known as "short returns" for failed conditions
localfunctionsomeFunction(param1,param2,param3)ifnot param1 thenreturnendprint('I met condition number one!')ifnot param2 thenreturnendprint('I met condition number two!')ifnot param3 thenreturnendprint('I met condition number three!')end
Native Usage
Always replace GetPlayerPed(-1) with PlayerPedId()
localfunctionsomeFunction()local ped =GetPlayerPed(-1) -- Don't use thislocal ped =PlayerPedId() -- Use thisend
Always replace GetDistanceBetweenCoords with lua math aka #(vector3 - vector3)
localfunctionsomeFunction()local ped =PlayerPedId()local pCoords =GetEntityCoords(ped)local coords =vector3(-29.53, -1103.67, 26.42)local dist =GetDistanceBetweenCoords(pCoords, coords, true) -- Don't use thislocal dist =#(pCoords - coords) -- Use thisif dist >5thenprint('Im within 5 distance units of the coords!')endend
Loops
Control your while loops and when they run
localfunctionexampleLoop()CreateThread(function()while listen doprint('running while loop only when needed')Wait(1)endend)endlocal listen =falseCreateThread(function() LoopZone = CircleZone:Create(vector3(-851.63, 74.36, 51.86), 5.0, { name ="ExampleLoop", debugPoly =true, }) LoopZone:onPlayerInOut(function(isPointInside)if isPointInside then listen =trueexampleLoop() -- Initiate loopelse listen =false-- turns off when your outside the zoneendend)end)
If you do have to create a thread that includes a "while" loop, always avoid using "while true do" if able. If you have to use this, follow the next tip, and it wonât impact performance as much
Control your thread times by using a variable that changes the wait time retroactively. So you can set the thread wait time to say 1000ms which checks for your if statement every second and if it makes it into the statement you can lower the wait time by just changing the variable value. Wait(sleep)
CreateThread(function()whiletruedoWait(1) inRange =falselocal pos =GetEntityCoords(PlayerPedId())if#(pos -vector3(-829.11, 75.03, 52.73)) <10.0then inRange =trueprint('Im in range and the loop runs faster')elseprint('Im not in range so i run only onces every 2.5 seconds')endifnot inRange thenWait(2500)endendend)
If you have job specific loops, make sure they only apply to players with that job. There's no reason for someone who is not a cop to be running a loop on their machine that does not apply to them
localfunctionexampleJobLoop()local job = QBCore.Functions.GetPlayerData().job.nameCreateThread(function()while job =='police' doprint('im a policeman!')Wait(1)endend)end
Security
A surplus amount of security in a code is not a bad thing. Don't be afraid to add in multiple if checks or create random variables to pass through your events
Never do any type of transaction with the player regarding money or items on the client side of a resource
Event Handlers
When setting variables inside your resource, handlers come in especially handy due to not needing to constantly run checks
-- These are client-side exampleslocal isLoggedIn =falselocal PlayerData = {}AddStateBagChangeHandler('isLoggedIn', nil, function(_,_,value) -- FiveM native methodif value then isLoggedIn =true PlayerData = QBCore.Functions.GetPlayerData()else isLoggedIn =false PlayerData = {}endend)AddEventHandler('QBCore:Client:OnPlayerLoaded', function() -- Don't use this with the native method isLoggedIn =true PlayerData = QBCore.Functions.GetPlayerData()end)RegisterNetEvent('QBCore:Client:OnPlayerUnload', function() -- Don't use this with the native method isLoggedIn =false PlayerData = {}end)RegisterNetEvent('QBCore:Client:OnJobUpdate', function(JobInfo) PlayerData.job = JobInfoend)RegisterNetEvent('QBCore:Player:SetPlayerData', function(val) PlayerData = valend)