DrawMarker, Hilfetexte und lib.showTextUI ohne Lag in FiveM
Zeichne Marker und zeige 'Drücke E'-Aufforderungen in FiveM ohne eine schwere Schleife: DrawMarker nur wenn in der Nähe, Hilfetext-Natives, lib.showTextUI und ox_lib Punkte für Zonen.
Du zeichnest einen Marker, gehst zu ihm und er flimmert, oder er zeigt sich nie, oder dein Skript sitzt bei 0.30 ms in resmon und tut nichts. Marker und „Drücke E"-Aufforderungen sehen einfach aus, aber sie sind die klassische Quelle von schweren Schleifen. Dieser Artikel zeigt, wie man einen Marker korrekt zeichnet, wie man eine Aufforderung zeigt und wie man nicht dafür zahlt, wenn der Spieler weit weg ist.
DrawMarker muss jeden Frame laufen
Ein Marker wird für einen Frame jedes Mal gezeichnet, wenn du DrawMarker aufrufst. Um ihn auf dem Bildschirm zu halten, rufst du ihn jeden Frame in einer Schleife mit Wait(0) auf:
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)Das funktioniert, aber es läuft jeden Frame für die ganze Sitzung, auch wenn der Spieler auf der anderen Seite der Karte ist. Behebe das als nächstes.
Zeichne nur, wenn der Spieler in der Nähe ist
Messe die Entfernung und schlaf länger, wenn der Spieler weit weg ist. Nur der nahe Zustand braucht 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)Weit weg wacht die Schleife einmal pro Sekunde auf und macht eine Subtraktion. In der Nähe des Markers läuft sie pro Frame, nur während sie es braucht. Warum das wichtig ist und wie man es in Resmon liest, ist in Resmon hohe ms: Wie optimiert man.
Tipp:
#(a - b)ist die Länge eines Vektor-Unterschieds, die Entfernung. Es brauchtvec3-Werte, dieGetEntityCoordsbereits zurückgibt.
Marker-Typen
Das erste Argument ist der Marker-Typ, eine Zahl. Ein paar, die Server viel verwenden:
| Typ | Sieht aus wie |
|---|---|
1 |
Ein Zylinder |
2 |
Ein Chevron-Pfeil (drehe ihn 180 Grad auf X um nach unten zu zeigen) |
23 |
Ein flacher Ring auf dem Boden |
25 |
Ein flacher Ring auf dem Boden, dünner |
Die vollständige Liste der Typen ist auf der FiveM-Dokumentationsseite unter Spielreferenzen, Marker. Die Skalierungs-Argumente ändern die Größe und der letzte Farbwert ist der Alpha (Transparenz). Platziere einen Boden-Marker bei z - 1.0, so dass er auf dem Boden sitzt, nicht auf der Taille des Spielers.
Hilfetext: die eingebaute Aufforderung
Das Spiel hat eine Hilfemeldung oben links auf dem Bildschirm. Du definierst eine Beschriftung, dann zeigst sie jeden Frame an, während der Spieler in Reichweite ist:
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~ wird durch die Taste ersetzt, die der Spieler für die Kontext-Aktion verwendet, standardmäßig E. Rufe showHelp() im distance < 1.5-Zweig oben auf, überprüfe dann die Taste:
if distance < 1.5 then
showHelp()
if IsControlJustReleased(0, 38) then
print('opened')
end
endRegistriere die Beschriftung einmal oben in der Datei, nicht innerhalb der Schleife.
lib.showTextUI und lib.hideTextUI
Mit ox_lib kannst du eine gestylte Aufforderung zeigen, und du rufst sie einmal auf, wenn der Spieler eintritt, nicht jeden Frame:
lib.showTextUI('[E] Open the garage', {
position = 'right-center',
icon = 'warehouse',
})
-- when the player leaves:
lib.hideTextUI()lib.isTextUIOpen() sagt dir, ob eine bereits auf dem Bildschirm ist. Es braucht shared_script '@ox_lib/init.lua' im Manifest (siehe der ox_lib-Menü-Leitfaden). Der Text ist nicht an eine Taste gebunden: Du überprüfst die Taste immer noch selbst oder verwendest eine Keybind.
ox_lib Punkte: gar keine Entfernungs-Schleife
Das Schreiben der Entfernungs-Schleife von Hand für jede Zone addiert sich auf. lib.points macht es für dich: ox_lib überprüft die Entfernung des Spielers zu allen Punkten zusammen und läuft deinen Code nur in der Nähe von ihnen:
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
endWie es funktioniert:
onEnterläuft einmal, wenn der Spieler innerhalb derdistancekommt.onExitläuft einmal, wenn sie geht.nearbyläuft jeden Frame, während sie innerhalb derdistancesind und sonst überhaupt nicht. Das ist, woDrawMarkergeht.self.currentDistanceist die aktuelle Entfernung zum Punkt.
Du kannst Hunderte von Punkten erstellen und nur die, bei denen der Spieler in der Nähe ist, kosten etwas. Entferne einen Punkt, den du nicht mehr brauchst mit point:remove().
Welches zu verwenden
- Ein oder zwei Zonen: die Entfernungs-Schleife mit Schlaf ist in Ordnung.
- Viele Zonen oder ein Skript, das Zonen aus Konfiguration erstellt: verwende
lib.points. - Interaktionen auf Objekten und Peds: Ein Ziel ist besser als ein Marker. Siehe ox_target: Wie man Ziele hinzufügt.
Checkliste
| Symptom | Behebung |
|---|---|
| Marker flimmert oder zeigt einen Frame | Rufe DrawMarker jeden Frame in einer Wait(0)-Schleife auf |
| Skript kostet Resmon-Zeit im Leerlauf | Schlaf 500 bis 1000 ms wenn weit weg, Wait(0) nur wenn in der Nähe |
| Marker schwebt in der Luft | Zeichne ihn bei z - 1.0 |
| Aufforderungs-Text zeigt sich nie | Definiere ihn mit AddTextEntry, zeige ihn dann jeden Frame |
lib.showTextUI bleibt auf dem Bildschirm |
Rufe lib.hideTextUI() beim Verlassen auf |
| Viele Zonen sind langsam | Verwende lib.points.new mit onEnter, onExit und nearby |
Kurze Antworten
Warum verschwindet mein Marker nach einem Frame?
DrawMarker muss jeden Frame in einer Schleife mit Wait(0) aufgerufen werden. Rufe es einmal auf und es zeigt sich für einen einzigen Frame.
Warum benutzt mein Skript so viel Resmon-Zeit?
Eine Wait(0)-Schleife, die die Entfernung zu jedem Marker misst, läuft jedes Frame die ganze Zeit. Schlaf länger, wenn der Spieler weit weg ist, oder verwende ox_lib-Punkte, so dass die Schleife nur in der Nähe der Zone läuft.
Welches ist besser, Hilfetext oder lib.showTextUI?
Hilfetext ist ins Spiel eingebaut und braucht keine Ressource. lib.showTextUI ist eine gestylte Aufforderung von ox_lib und ist einfach zu zeigen und zu verbergen aus dem Code. Wähle einen Stil und halte ihn für deinen ganzen Server.
Scripts ohne dieses Problem
Advanced BoostingFahrzeug-Boosting per Tablet: Aufträge von Klasse D bis S+, Crews und eine Live-Warteschlange.Script ansehen →
Shop CreatorBau einen Shop in unter einer Minute — Besitzer, Angestellte, Tresore und Überfälle inklusive.Script ansehen →
Quest CreatorEin visueller Editor für Quests und NPC-Dialoge, Node für Node im Spiel gebaut.Script ansehen →