PiTyUs.Hire me

Getting started

Write your first FiveM script, step by step

A beginner FiveM scripting tutorial: create a resource, write fxmanifest.lua, add a /car command that spawns a vehicle with RequestModel and CreateVehicle, talk to the server, and test it with ensure and the F8 console.

Updated 14 min readBy PiTyUs · FiveM developer

Overview

Reading about FiveM scripting only goes so far; the moment it clicks is when your own command does something in the game. In this tutorial you build a small but complete resource from an empty folder: a /car command that spawns any vehicle, a message sent to the server, and a log line printed back. Every file is shown in full, and every line is explained.

What you need

01Step 1: create the resource

Inside your server’s resources folder, create a folder named my_first with three files:

Folder layouttext
resources/
└── my_first/
    ├── fxmanifest.lua
    ├── client.lua
    └── server.lua
fxmanifest.lualua
fx_version 'cerulean'
game 'gta5'

name 'my_first'
description 'My first FiveM resource'

client_script 'client.lua'
server_script 'server.lua'

The manifest tells FiveM this folder is a resource, that it targets GTA V, and which file runs where. What a FiveM resource is explains every directive.

02Step 2: the client script

This runs in each player’s game. It registers a /car command that takes a model name, loads the model, spawns the vehicle in front of the player and puts them in the driver’s seat.

client.lualua
RegisterCommand('car', function(source, args)
    local modelName = args[1] or 'adder'
    local model = joaat(modelName)

    -- 1. Is it a real vehicle model?
    if not IsModelInCdimage(model) or not IsModelAVehicle(model) then
        print(('"%s" is not a vehicle model'):format(modelName))
        return
    end

    -- 2. Load it (with a timeout so we never wait forever)
    RequestModel(model)
    local timeout = GetGameTimer() + 5000
    while not HasModelLoaded(model) do
        if GetGameTimer() > timeout then
            print('model took too long to load')
            return
        end
        Wait(0)
    end

    -- 3. Spawn it where the player stands, facing the same way
    local ped = PlayerPedId()
    local pos = GetEntityCoords(ped)
    local heading = GetEntityHeading(ped)
    local vehicle = CreateVehicle(model, pos.x, pos.y, pos.z, heading, true, false)

    -- 4. Seat the player and tidy up
    SetPedIntoVehicle(ped, vehicle, -1) -- -1 is the driver seat
    SetModelAsNoLongerNeeded(model)

    -- 5. Tell the server
    TriggerServerEvent('my_first:spawned', modelName)
end, false)
LineWhat it does
joaat(modelName)Turns the text name into the model hash the game uses.
IsModelInCdimage / IsModelAVehicleChecks the model exists and is a vehicle, so typos do not hang.
RequestModel + HasModelLoadedAsks the game to load the model and waits until it is in memory.
Wait(0)Yields one frame so the game keeps running while you wait.
CreateVehicle(..., true, false)Spawns a networked vehicle so other players can see it.
SetPedIntoVehicle(ped, vehicle, -1)Puts the player in the driver seat.
SetModelAsNoLongerNeededLets the game unload the model when it is not in use.
TriggerServerEventSends a message to the server script.

03Step 3: the server script

server.lualua
RegisterNetEvent('my_first:spawned', function(modelName)
    local src = source
    local name = GetPlayerName(src)
    print(('%s (id %d) spawned a %s'):format(name, src, tostring(modelName)))
end)

RegisterNetEvent allows the event to be triggered from clients, and source is the ID of the player who sent it. Store it in a local immediately — its value changes as soon as your handler waits. More in FiveM events explained.

04Step 4: run it

  1. Add ensure my_first to server.cfg, after your framework if you have one.
  2. Start (or restart) the server and join it.
  3. Open chat (T) and type /car sultan.
  4. Check the server console for the line … spawned a sultan.
  5. Change something in client.lua, then type ensure my_first in the server console (or F8 with permission) to reload.

Where to go from here

This script is fine for a private test server. Before putting anything like it on a public server, three things change:

  • Anyone can spawn anything — restrict the command with an ACE permission as shown in commands and key mapping.
  • Spawning on the server with OneSync is more robust — see server-side entities.
  • On a framework server, vehicles belong in the garage system, not a free command.

To understand the language itself, continue with Lua basics for FiveM.

Frequently asked questions

How do I make a FiveM script?

Create a folder in resources, add an fxmanifest.lua that lists your client and server scripts, write the scripts, add ensure foldername to server.cfg and restart the server.

Why does my car not spawn?

Most often the model was not loaded before CreateVehicle, or the model name is wrong. Request the model and wait for HasModelLoaded, and check the name with IsModelInCdimage.

Do I need to restart the whole server to test changes?

No. Type ensure yourresource in the server console to restart just that resource.

Where do print() messages appear?

Client-side prints appear in the F8 console in game; server-side prints appear in the server console or txAdmin’s live console.

What does -1 mean in SetPedIntoVehicle?

It is the seat index for the driver. 0 is the front passenger, 1 and 2 the rear seats.

Need this built, not just explained?

Ten years of FiveM work, from Lua to NUI

Custom resources, React NUI, ESX / QBCore / Qbox integration, OneSync performance audits and security reviews — plus the websites and SEO around your server brand.

Related guides