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) :
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) :
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 valeursvec3, queGetEntityCoordsretourne 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 :
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 :
if distance < 1.5 then
showHelp()
if IsControlJustReleased(0, 38) then
print('opened')
end
endEnregistrez 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 :
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 :
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
endComment cela fonctionne :
onEnters'exécute une fois quand le joueur vient à l'intérieur dedistance.onExits'exécute une fois quand il sort.nearbys'exécute chaque frame pendant qu'il est à l'intérieur dedistance, et pas du tout sinon. C'est oùDrawMarkerva.self.currentDistanceest 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 →