Whilst searching through the FiveM docs, and reading the Lua tutorials, I came across this tidbit;
Now, we call REQUEST_MODEL to load the actual vehicle model. This native takes a Hash argument, but in Lua you can also just pass a string and it’ll be converted to a hash. You’ll often see people use GetHashKey (GET_HASH_KEY), but if the native is specified as taking a Hash , you actually don’t need this.
Now I’m also aware of the use of tildes’ or ’ model ’ to convert a string to a hash, as well as joaat(model) and of course the native. The question I pose is, what’s the most optimal way to get a hash for a RequestModel or similar call?
Should I as a developer convert to a hash before using a function, to relieve strain or allow the natives like RequestModel convert the string to a hash themselves?
I mean it really depends on what you are trying to accomplish.
If you have a script that has some models predefined in a table, convert it into a hash table.
-- "normal"
local models = {
"model_name_1",
"model_name_2",
"model_name_3"
}
-- "hashed"
local modelHashs = {
`model_name_1`,
`model_name_2`,
`model_name_3`
}
Then you can just work with the hashs directly and have no overhead whatsoever inside your actual spawning code.
If you are spawning vehicles or something like that via a command that let’s you define the model yourself, just immediately use the hash or convert it into one.
RegisterCommand("v", function(src, args, raw)
local model = args[1]
-- check if user already input a number/hash or hash it yourself
local hash = tonumber(model)
if (not hash) then
hash = joaat(model)
end
-- use hash for spawning or whatever
end, false)
GetHashKey should be avoided as it is a native call which results in a much higher overhead than actually necessary in most cases.
That being said, if you greatly limit its use to just a simple function call. Why not? If it makes the code more readable for you.
Simple answer: Don’t spam any native calls. Try to only call them once and save the result in a variable and use that one. Hashes don’t change. They always stay the same for the same input data.
So that’s exactly what I’ve been doing mostly, storing static models in a table with tildes’ and joaat() when I need it dynamically.
I guess what threw me off, was the fact that some natives, whose parameter is marked as a hash, can actually convert a string to a hash inside the function: ie RequestModel(‘adder’).
So my question really was, are we better off converting it to a hash before calling the native or just let the native do the grunt work? (I guess this would depend on what method the native uses to convert the string to a hash).
To be quite honest, I didn’t even know that was a thing until now that you mentioned it.
But as you already said, only “some” of the natives work like that. Sooo I would still go with what I usually do as it is at least consistent.
Also if RequestModel takes a string and e.g. HasModelLoaded requires a hash, you would need to do it anyways.
Well, I just tested this using the following code:
function SpawnVehicle(model)
RequestModel(model)
while (not HasModelLoaded(model)) do
Wait(0)
end
local veh = CreateVehicle(model, GetEntityCoords(PlayerPedId()), 0.0, true, true)
end
RegisterCommand("v1", function(src, args, raw)
SpawnVehicle(joaat(args[1]))
end, false)
RegisterCommand("v2", function(src, args, raw)
SpawnVehicle(args[1])
end, false)
And both of the work on a 5848 server and current beta client build.
Also done some testing regarding performance using the following code:
RegisterCommand("perf", function(src, args, raw)
local model = "adder"
Wait(0)
for i = 1, 100000 do
RequestModel(model)
HasModelLoaded(model)
end
Wait(0)
print("string:", GetFrameTime())
model = `adder`
Wait(0)
for i = 1, 100000 do
RequestModel(model)
HasModelLoaded(model)
end
Wait(0)
print("hash:", GetFrameTime())
end, false)
Using the string version seems to be slower at 60% of the hash version. But it barely makes any sort of difference if you call it only once. I also tried it with “just a thousand times” and they are basically the same.
Tested on a beefy system (Ryzen 7 5800x, Zotac GTX 1080 Amp Extreme, ~100-180fps) and the worst client side resources were the default chat and the spawnmanager xD
I was just testing this then, but you beat me to the punch! So it’s definitely better to first convert static tables using tildes’ and dynamic ones using joaat(model) BUT it’s a negligible difference.