Spawn a vehicle in FiveM: CreateVehicle vs CreateVehicleServerSetter

Spawn vehicles the right way in FiveM: client CreateVehicle with RequestModel, server CreateVehicleServerSetter on OneSync, net ids, plates, keys and vanishing cars.

You spawn a vehicle and it appears invisible, spawns under the map, vanishes after a minute, or only the player who spawned it can see it. There are two correct ways to spawn a car, and each has a different set of pitfalls. This article shows both, how to set the plate and hand over the keys, and why spawned cars disappear.

Spawn on the client with CreateVehicle

The client version is the one most scripts use. The model must be loaded before you create the vehicle, or CreateVehicle returns 0:

lua
local function spawnVehicle(modelName, coords, heading)
    local model = joaat(modelName)

    if not IsModelInCdimage(model) or not IsModelAVehicle(model) then
        print('invalid vehicle model:', modelName)
        return nil
    end

    RequestModel(model)
    local timeout = GetGameTimer() + 5000
    while not HasModelLoaded(model) do
        if GetGameTimer() > timeout then
            print('model did not load:', modelName)
            return nil
        end
        Wait(0)
    end

    local vehicle = CreateVehicle(model, coords.x, coords.y, coords.z, heading, true, false)
    SetModelAsNoLongerNeeded(model)

    return vehicle
end

The steps:

  1. IsModelInCdimage checks that the model exists. A typo or a missing addon car stops here instead of freezing.
  2. RequestModel then a loop on HasModelLoaded waits for it, with a timeout.
  3. CreateVehicle takes the model, position, heading, then isNetwork (true so other players see it) and netMissionEntity.
  4. SetModelAsNoLongerNeeded frees the model memory when you are done.

If the vehicle is an addon, see how to add addon cars first. A model that is not streamed never loads.

Tip: with ox_lib, lib.requestModel(model) does the request and the wait for you, and errors out on a timeout.

Put the player in the driver seat and set the plate:

lua
local vehicle = spawnVehicle('sultan', GetEntityCoords(PlayerPedId()), GetEntityHeading(PlayerPedId()))

if vehicle then
    SetVehicleNumberPlateText(vehicle, 'MIC 001')
    SetPedIntoVehicle(PlayerPedId(), vehicle, -1)
end

The plate holds at most 8 characters.

Spawn on the server with CreateVehicleServerSetter

On OneSync, the server can create the vehicle itself. This is more reliable for scripts where the server decides the spawn, such as a garage or a job vehicle, and no client has to stay close:

lua
RegisterNetEvent('my_script:spawnCar', function()
    local src = source
    local ped = GetPlayerPed(src)
    local coords = GetEntityCoords(ped)
    local heading = GetEntityHeading(ped)

    local vehicle = CreateVehicleServerSetter(joaat('sultan'), 'automobile', coords.x, coords.y, coords.z, heading)

    while not DoesEntityExist(vehicle) do
        Wait(0)
    end

    SetVehicleNumberPlateText(vehicle, 'MIC 001')
    TaskWarpPedIntoVehicle(ped, vehicle, -1)

    local netId = NetworkGetNetworkIdFromEntity(vehicle)
    TriggerClientEvent('my_script:vehicleSpawned', src, netId)
end)

The second argument is the vehicle type as a string: 'automobile', 'bike', 'boat', 'heli', 'plane', 'submarine', 'trailer' or 'train'. Pick the one that matches the model. A bike created as an automobile will behave wrongly.

Unlike the client, you do not request the model on the server. The call is also asynchronous: the entity may not exist the moment it returns, so wait for DoesEntityExist, with a timeout in real code.

Enable OneSync in server.cfg, or the call does not work. See how to enable OneSync.

Net ids: handing the car to a client

A vehicle created on the server has an entity handle that only exists on the server. A client cannot use it. To reference the car across machines, use its network id, which is the same everywhere:

lua
-- server
local netId = NetworkGetNetworkIdFromEntity(vehicle)

On the client, wait for the entity to exist on that machine, then convert:

lua
RegisterNetEvent('my_script:vehicleSpawned', function(netId)
    local timeout = GetGameTimer() + 5000
    while not NetworkDoesEntityExistWithNetworkId(netId) do
        if GetGameTimer() > timeout then return end
        Wait(0)
    end

    local vehicle = NetToVeh(netId)
    print('my vehicle is', vehicle)
end)

Never send the raw entity handle over an event: it means nothing on another machine.

Plates and keys

Set the plate right after the vehicle exists, as in the examples above, and before you hand over the keys. The keys depend on your vehicle keys script, since each script has its own function. Most work with the plate, so the usual order is:

  1. Create the vehicle.
  2. Set the plate with SetVehicleNumberPlateText.
  3. Call your keys script's export or event with that plate.

Store the same plate in your database, if the vehicle is owned, so the garage can find it again. Check the documentation of the keys script you use for the exact call. Do not copy a call from another server.

Why spawned cars disappear

Not relevant to anyone. The game removes a networked entity when nobody is near it. A car spawned on the server for a player who then moves away can be deleted.

The owner left. An entity belongs to a player who owns it. When a client-spawned vehicle's owner disconnects or moves out of range, it may be removed. On the server you can set what happens:

lua
SetEntityOrphanMode(vehicle, 2)

The orphan mode 2 is "keep the entity", 0 is the default (delete when not relevant), and 1 deletes it when the owner disconnects. Check the native's documentation for your server build.

Not marked as a mission entity. On the client, ambient cleanup can delete a car you created. Mark it so the game treats it as yours:

lua
SetEntityAsMissionEntity(vehicle, true, true)

A cleanup script. Many servers run a script that removes unoccupied vehicles. If your cars vanish at a fixed time, that is the cause, not your spawn code.

It never spawned. An invisible or missing car often means the model was not loaded, CreateVehicle returned 0 and the script went on. Always check the returned handle.

Delete cars yourself when you are done, with DeleteEntity(vehicle), so they do not pile up.

Checklist

Symptom Fix
CreateVehicle returns 0 RequestModel and wait for HasModelLoaded first
Freeze on a bad model name Check IsModelInCdimage before requesting
Only the spawner sees the car Pass isNetwork = true to CreateVehicle
CreateVehicleServerSetter does nothing Enable OneSync and wait for DoesEntityExist
Client gets a useless entity id Send the net id, then use NetToVeh on the client
Car disappears later Mark as mission entity, set the orphan mode, check cleanup scripts
Player cannot drive their car Give the keys with your keys script, using the plate

Quick answers

Do I need OneSync to use CreateVehicleServerSetter?

Yes. Server-side entity creation needs OneSync enabled. On a server without it, spawn the vehicle on the client with CreateVehicle.

Why does my spawned car disappear?

A networked vehicle is deleted when it is no longer relevant to anyone, or when its owner leaves, unless you tell the game to keep it. Mark it as a mission entity on the client, or set its orphan mode on the server.

How do I give the player the keys?

It depends on the vehicle keys script your server uses. Most have a client export or event that takes the plate, so call that after setting the plate.

Scripts that skip this problem

Advanced BoostingTablet-driven vehicle boosting: contracts from class D to S+, crews and a live queue.View script →Chameleon Paints82 colour-shifting chameleon paints in one click-to-apply menu.View script →

Keep reading