Retour au cours

games / fivem

Natives essentielles : joueur, ped, véhicules, monde

Leçon 51 exercice

Explication

Ce que vous allez apprendre

  • Récupérer le ped du joueur et sa position avec PlayerPedId/GetEntityCoords
  • Manipuler un véhicule (verrouillage, carburant, moteur) via les natives dédiées
  • Charger un modèle correctement avec RequestModel avant de créer un véhicule ou un ped
  • Libérer un modèle chargé avec SetModelAsNoLongerNeeded pour éviter les fuites mémoire
  • Ajouter un blip sur la carte et détecter ce qu'un joueur regarde (raycast)

Dans quel contexte ?

Un script doit faire apparaître un véhicule spécifique à un endroit précis dès qu'un joueur tape une commande, avec une icône correspondante sur la carte. Ce cas d'usage très courant illustre parfaitement le cycle de vie d'un modèle FiveM : demander son chargement, attendre qu'il soit prêt, créer l'objet, puis libérer la mémoire une fois que ce n'est plus nécessaire — une séquence que beaucoup de débutants raccourcissent par erreur, avec des objets invisibles ou des crashs à la clé.

NativeRôle
PlayerPedId()Entité contrôlée localement (client uniquement)
RequestModel(hash)Demande le chargement d'un modèle en mémoire
HasModelLoaded(hash)Vérifie si le chargement est terminé
SetModelAsNoLongerNeeded(hash)Libère la mémoire du modèle après usage

Piège fréquent

Appeler CreateVehicle ou CreatePed immédiatement après RequestModel, sans attendre HasModelLoaded dans une boucle, crée souvent un objet invisible ou provoque une erreur silencieuse : le modèle n'a pas encore fini de se charger depuis le disque ou le réseau.

Le vocabulaire du moteur de jeu

Le jeu GTA V, sur lequel FiveM repose, est lui-même écrit dans un autre langage (C++). Pour permettre au code Lua d'interagir avec ce moteur — déplacer un personnage, faire apparaître un véhicule, dessiner une icône sur la carte — FiveM expose des milliers de fonctions prêtes à l'emploi appelées natives. Une native n'est donc pas une fonction qu'on écrit soi-même : c'est une porte d'entrée déjà construite vers une fonctionnalité du jeu.

PlayerPedId : le point de départ de presque tout

PlayerPedId() est probablement la native la plus utilisée en scripting client : elle retourne l'identifiant du personnage ("ped", pour "pedestrian") que le joueur contrôle actuellement. Un point important vu dans la leçon précédente : cette native n'a de sens que côté client, puisque le serveur ne connaît rien du monde 3D.

Pourquoi charger un modèle prend du temps

Créer un véhicule ou un personnage à partir d'un modèle 3D n'est pas instantané : ce modèle doit d'abord être "streamé", c'est-à-dire chargé en mémoire depuis le disque ou le réseau. C'est pour cela qu'on doit systématiquement demander le chargement (RequestModel) puis attendre, dans une petite boucle, que ce chargement soit effectivement terminé, avant de tenter de créer l'objet — sauter cette étape crée des objets invisibles ou provoque des erreurs.

Ne pas oublier de libérer la mémoire

Une fois un modèle utilisé, il reste chargé en mémoire tant qu'on ne signale pas explicitement qu'on n'en a plus besoin (SetModelAsNoLongerNeeded). Sur un serveur où des dizaines de scripts créent régulièrement des véhicules ou des personnages, oublier cette étape provoque une accumulation progressive de mémoire utilisée pour rien — un classique des ressources mal écrites qui finissent par ralentir tout le serveur au fil du temps.

Commandes & code

Natives essentielles

Les "natives" sont les fonctions du moteur du jeu, exposées à Lua. Voici les plus utilisées côté client.

lua
-- Joueur et ped
local ped = PlayerPedId()
local coords = GetEntityCoords(ped)
local heading = GetEntityHeading(ped)

SetEntityCoords(ped, coords.x + 5.0, coords.y, coords.z, false, false, false, true)
SetEntityHeading(ped, 180.0)

-- Santé / armure
SetEntityHealth(ped, 200)
SetPedArmour(ped, 100)
lua
-- Véhicules
local vehicle = GetVehiclePedIsIn(ped, false)
if vehicle ~= 0 then
    SetVehicleFuelLevel(vehicle, 100.0)
    SetVehicleDoorsLocked(vehicle, 2) -- 2 = verrouillé
    SetVehicleEngineOn(vehicle, true, true, false)
end

-- Spawn d'un véhicule (pattern classique de chargement de modèle)
local function SpawnVehicle(model, coords, heading)
    local hash = GetHashKey(model)
    RequestModel(hash)

    while not HasModelLoaded(hash) do
        Wait(10) -- attendre le streaming du modèle, sans bloquer le jeu (voir leçon Threads)
    end

    local veh = CreateVehicle(hash, coords.x, coords.y, coords.z, heading, true, false)
    SetModelAsNoLongerNeeded(hash) -- libère la mémoire une fois le véhicule créé
    return veh
end

local myCar = SpawnVehicle('adder', vector3(215.0, -810.0, 30.0), 90.0)
lua
-- Blips (icônes sur la carte)
local blip = AddBlipForCoord(coords.x, coords.y, coords.z)
SetBlipSprite(blip, 1)
SetBlipColour(blip, 2)
SetBlipScale(blip, 0.8)
SetBlipAsShortRange(blip, true)

BeginTextCommandSetBlipName("STRING")
AddTextComponentString("Boutique Technologik")
EndTextCommandSetBlipName(blip)
lua
-- Raycast : détecter ce que le joueur regarde (utilisé pour les interactions custom)
local function GetEntityPlayerIsLookingAt()
    local ped = PlayerPedId()
    local coords = GetEntityCoords(ped)
    local camRot = GetGameplayCamRot(2)
    local camCoord = GetGameplayCamCoord()

    local direction = RotationToDirection(camRot)
    local destination = camCoord + direction * 10.0

    local rayHandle = StartShapeTestRay(
        camCoord.x, camCoord.y, camCoord.z,
        destination.x, destination.y, destination.z,
        -1, ped, 0
    )
    local _, hit, _, _, entity = GetShapeTestResult(rayHandle)

    if hit == 1 then
        return entity
    end
    return nil
end

Résumé

  • PlayerPedId() retourne l'entité contrôlée localement ; jamais valable côté serveur.
  • Toujours utiliser RequestModel + boucle d'attente avant CreateVehicle/CreatePed avec un nouveau modèle.
  • Libérer les modèles avec SetModelAsNoLongerNeeded pour éviter les fuites mémoire.

Exercices pratiques

1 disponible
1

Mission : le véhicule qui apparaît invisible

Objectif : Corriger un cycle de chargement de modèle incomplet responsable d'un véhicule invisible et d'une fuite mémoire progressive.

Contexte

La commande /car adder d'un serveur de test spawn parfois un véhicule invisible ou provoque un léger freeze. Le code en cause est : RequestModel(GetHashKey('adder')); local veh = CreateVehicle(GetHashKey('adder'), x, y, z, heading, true, false), appelé directement l'un après l'autre, sans jamais libérer le modèle ensuite. La boutique de véhicules du serveur, qui utilise le même pattern des dizaines de fois par jour, voit la consommation mémoire du client augmenter lentement au fil des sessions.

Résoudre l’exercice →