How to Optimize Your FiveM Scripts
In this article, we'll explore methods to optimize your FiveM scripts for better performance and efficiency. We will also discuss some of the most common performace pitfalls and how to avoid them.
Reducing Native Calls
When using FiveM natives you should consider the following:
- Natives are quite slow, plain lua will always be faster
- Always cache the result of a native call where possible
Unoptimized Code
for k,v in pairs(something) do
local ped = PlayerPedId()
-- do something with ped
end
Optimized Code
local ped = PlayerPedId()
for k,v in pairs(something) do
-- do something with ped
end
In the unoptimized code, PlayerPedId()
is called every iteration of the loop. By storing the result of PlayerPedId()
in a variable before the loop, you reduce the number of native calls, which enhances performance.
Using PlayerPedId()
Many scripts use GetPlayerPed(-1)
. However, PlayerPedId()
serves the same purpose but is less costly in terms of performance.
local ped = PlayerPedId()
PlayerPedId()
is more efficient than GetPlayerPed(-1)
. Always prefer using PlayerPedId()
to reduce unnecessary performance overhead.
Improving Distance Checks
When checking a player's distance from a point, using Lua's vector mathematics is more efficient than native functions like Vdist
, Vdist2
, or GetDistanceBetweenCoords
.
Unoptimized Code
local distance = Vdist(playerPos.x, playerPos.y, playerPos.z, point.x, point.y, point.z)
Optimized Code
local pos1 = vector3(0.0, 10.0, 0.0)
local pos2 = vector3(0.0, 10.0, 10.0)
local dist = #(pos1 - pos2) -- Subtract the vectors and return the distance with #
Lua's built-in vector operations are more efficient and can reduce script execution time compared to the native distance functions.
Adjusting Wait() in Loops
Not all loops need to run every frame. Increasing the delay between iterations using Wait()
can greatly improve performance. It's also beneficial to separate loops based on their frequency of execution.
It might also be benificial to split up loops to make them more efficient.
Unoptimized Code
Citizen.CreateThread(function()
while true do
local ped = PlayerPedId()
local coords = GetEntityCoords(ped)
local dist = #(markerCoords - coords) -- markerCoords should be vec3
if dist < 50.0 then -- Don't draw marker if far away
DrawMarker(someplace, markerRadius)
if dist < markerRadius then -- If inside the marker, do some stuff, like show a menu etc.
-- do something
end
end
Wait(0) -- Wait until next frame
end
end)
Optimized Code
local markerInRange = false
-- Thread to check distance
Citizen.CreateThread(function()
while true do
local ped = PlayerPedId()
local coords = GetEntityCoords(ped)
local dist = #(markerCoords - coords) -- markerCoords should be vec3
if dist < 50.0 then
markerInRange = true
if dist < markerRadius then -- If inside the marker, do some stuff, like show a menu etc.
-- do something
end
else
markerInRange = false
end
Wait(500) -- Run this loop every 500 milliseconds
end
end)
-- Thread to draw the marker
Citizen.CreateThread(function()
while true do
if markerInRange then
DrawMarker(someplace, markerRadius)
Wait(0) -- Run every frame when marker is in range
else
Wait(500) -- Run this loop every 500 milliseconds when marker is out of range
end
end
end)
By separating the distance check from the marker drawing and adjusting the wait times appropriately, you can significantly reduce the load on your script, resulting in smoother performance. The distance check only needs to run twice per second, while the drawing function should run every frame when the marker is in range.
Conclusion
Implementing these optimizations will help you create more efficient and performant FiveM scripts. Reducing native calls, using efficient distance checks, and properly managing loop intervals are key practices for script optimization. By following these techniques, you can enhance the gameplay experience by reducing latency and improving overall performance.