DrawMarker, texte d'aide et lib.showTextUI sans lag dans FiveM

Dessinez des marqueurs et montrez des invites « Appuyez sur E » dans FiveM sans une boucle lourde : DrawMarker seulement quand proche, natives de texte d'aide, lib.showTextUI et points ox_lib pour les zones.

Vous dessinez un marqueur, vous vous en approchez et il clignote, ou il ne s'affiche jamais, ou votre script s'assoit à 0.30 ms dans resmon ne faisant rien. Les marqueurs et les invites « Appuyez sur E » ont l'air simple, mais ils sont la source classique de boucles lourdes. Cet article montre comment dessiner correctement un marqueur, comment afficher une invite, et comment arrêter de payer quand le joueur est loin.

DrawMarker doit s'exécuter chaque frame

Un marqueur est dessiné pour une frame chaque fois que vous appelez DrawMarker. Pour le garder à l'écran, vous l'appelez à nouveau chaque frame, dans une boucle avec Wait(0) :

lua
local coords = vec3(441.2, -981.9, 30.7)

CreateThread(function()
    while true do
        DrawMarker(
            1,                                  -- type: cylinder
            coords.x, coords.y, coords.z - 1.0, -- position (on the ground)
            0.0, 0.0, 0.0,                      -- direction
            0.0, 0.0, 0.0,                      -- rotation
            1.5, 1.5, 0.5,                      -- scale
            50, 150, 255, 120,                  -- red, green, blue, alpha
            false, false, 2, false, nil, nil, false
        )
        Wait(0)
    end
end)

Cela fonctionne, mais il s'exécute chaque frame pendant toute la session, même quand le joueur est à travers la carte. Corrigez cela ensuite.

Dessiner seulement quand le joueur est proche

Mesurez la distance et dormez plus longtemps quand le joueur est loin. Seulement l'état proche a besoin de Wait(0) :

lua
local coords = vec3(441.2, -981.9, 30.7)

CreateThread(function()
    while true do
        local sleep = 1000
        local pedCoords = GetEntityCoords(PlayerPedId())
        local distance = #(pedCoords - coords)

        if distance < 15.0 then
            sleep = 0
            DrawMarker(1, coords.x, coords.y, coords.z - 1.0,
                0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.5, 1.5, 0.5,
                50, 150, 255, 120, false, false, 2, false, nil, nil, false)

            if distance < 1.5 then
                -- show the prompt here (next section)
            end
        end

        Wait(sleep)
    end
end)

Loin, la boucle se réveille une fois par seconde et fait une soustraction. Près du marqueur, elle s'exécute par frame, seulement pendant qu'elle en a besoin. Pourquoi cela importe, et comment le lire dans resmon, est dans resmon high ms : comment optimiser.

Conseil : #(a - b) est la longueur d'une différence vectorielle, la distance. Il a besoin de valeurs vec3, que GetEntityCoords retourne déjà.

Types de marqueurs

Le premier argument est le type de marqueur, un nombre. Quelques-uns que les serveurs utilisent beaucoup :

Type Ressemble à
1 Un cylindre
2 Une flèche en chevron (la rotation 180 degrés sur X pour pointer vers le bas)
23 Un anneau plat sur le sol
25 Un anneau plat sur le sol, plus mince

La liste complète des types est sur le site de documentation FiveM, sous références de jeu, marqueurs. Les arguments d'échelle changent la taille, et la dernière valeur de couleur est l'alpha (transparence). Placez un marqueur de sol à z - 1.0 pour qu'il s'assoie sur le sol, pas flottant à la taille du joueur.

Texte d'aide : l'invite intégrée

Le jeu a un message d'aide en haut à gauche de l'écran. Vous définissez un label, puis l'affichez chaque frame pendant que le joueur est à portée :

lua
AddTextEntry('MY_SCRIPT_HELP', 'Press ~INPUT_CONTEXT~ to open the garage')

local function showHelp()
    BeginTextCommandDisplayHelp('MY_SCRIPT_HELP')
    EndTextCommandDisplayHelp(0, false, true, -1)
end

~INPUT_CONTEXT~ est remplacé par la touche que le joueur utilise pour l'action contextuelle, qui est E par défaut. Appelez showHelp() à l'intérieur de la branche distance < 1.5 ci-dessus, puis vérifiez la touche :

lua
if distance < 1.5 then
    showHelp()
    if IsControlJustReleased(0, 38) then
        print('opened')
    end
end

Enregistrez le label une fois en haut du fichier, pas à l'intérieur de la boucle.

lib.showTextUI et lib.hideTextUI

Avec ox_lib, vous pouvez afficher une invite stylisée, et vous l'appelez une fois quand le joueur entre, pas chaque frame :

lua
lib.showTextUI('[E] Open the garage', {
    position = 'right-center',
    icon = 'warehouse',
})

-- when the player leaves:
lib.hideTextUI()

lib.isTextUIOpen() vous dit si une est déjà à l'écran. Cela a besoin de shared_script '@ox_lib/init.lua' dans votre manifest (voir le guide du menu ox_lib). Le texte n'est pas lié à une touche : vous vérifiez toujours la touche vous-même, ou utilisez une liaison de touche.

Points ox_lib : pas de boucle de distance du tout

Écrire la boucle de distance à la main pour chaque zone s'accumule. lib.points le fait pour vous : ox_lib vérifie la distance du joueur à tous les points ensemble, et n'exécute votre code que près d'eux :

lua
local point = lib.points.new({
    coords = vec3(441.2, -981.9, 30.7),
    distance = 15.0,
})

function point:onEnter()
    lib.showTextUI('[E] Open the garage')
end

function point:onExit()
    lib.hideTextUI()
end

function point:nearby()
    DrawMarker(1, self.coords.x, self.coords.y, self.coords.z - 1.0,
        0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.5, 1.5, 0.5,
        50, 150, 255, 120, false, false, 2, false, nil, nil, false)

    if self.currentDistance < 1.5 and IsControlJustReleased(0, 38) then
        print('opened')
    end
end

Comment cela fonctionne :

  • onEnter s'exécute une fois quand le joueur vient à l'intérieur de distance.
  • onExit s'exécute une fois quand il sort.
  • nearby s'exécute chaque frame pendant qu'il est à l'intérieur de distance, et pas du tout sinon. C'est où DrawMarker va.
  • self.currentDistance est la distance courante au point.

Vous pouvez créer des centaines de points et seulement les uns près desquels le joueur est coûtent quelque chose. Supprimez un point que vous n'avez plus besoin avec point:remove().

Lequel utiliser

  • Une ou deux zones : la boucle de distance avec un sommeil est bien.
  • Beaucoup de zones, ou un script qui crée des zones à partir de la config : utilisez lib.points.
  • Interactions sur des objets et des peds : une cible est mieux qu'un marqueur. Voir ox_target : comment ajouter des cibles.

Checklist

Problème Solution
Le marqueur clignote ou s'affiche pendant une frame Appelez DrawMarker chaque frame dans une boucle Wait(0)
Le script coûte du temps resmon quand inactif Dormez 500 à 1000 ms quand loin, Wait(0) seulement quand proche
Le marqueur flotte en l'air Dessinez-le à z - 1.0
Le texte d'invite ne s'affiche jamais Définissez-le avec AddTextEntry, puis affichez-le chaque frame
lib.showTextUI reste à l'écran Appelez lib.hideTextUI() à la sortie
Beaucoup de zones sont lentes Utilisez lib.points.new avec onEnter, onExit et nearby

Réponses rapides

Pourquoi mon marqueur disparaît après une frame ?

DrawMarker doit être appelé chaque frame, dans une boucle avec Wait(0). Appelez-le une fois et il s'affiche pour une seule frame.

Pourquoi mon script utilise-t-il beaucoup de temps resmon ?

Une boucle Wait(0) qui mesure la distance à chaque marqueur s'exécute chaque frame tout le temps. Dormez plus longtemps quand le joueur est loin, ou utilisez les points ox_lib pour que la boucle s'exécute seulement près de la zone.

Lequel est mieux, texte d'aide ou lib.showTextUI ?

Le texte d'aide est intégré au jeu et n'a besoin de ressource. lib.showTextUI est une invite stylisée d'ox_lib et est facile à afficher et cacher depuis le code. Choisissez un style et gardez-le pour tout votre serveur.

Des scripts sans ce problème

Advanced BoostingDu boosting de véhicules piloté par tablette : contrats de classe D à S+, crews et file d’attente en direct.Voir le script →Shop CreatorCréez un magasin en moins d’une minute — propriétaires, employés, coffres et braquages inclus.Voir le script →Quest CreatorUn éditeur visuel de quêtes et de dialogues PNJ, construit nœud par nœud en jeu.Voir le script →

À lire aussi