DrawMarker, help text e lib.showTextUI senza lag in FiveM

Disegna marcatori e mostra i prompt 'Press E' in FiveM senza un loop pesante: DrawMarker solo quando vicino, nativi di testo help, lib.showTextUI e punti ox_lib per le zone.

Disegni un marcatore, ti avvicini e sfarfalla, o non appare mai, o il tuo script rimane a 0.30 ms in resmon senza fare nulla. I marcatori e i prompt "Press E" sembrano semplici, ma sono la fonte classica di loop pesanti. Questo articolo mostra come disegnare un marcatore correttamente, come mostrare un prompt, e come smettere di pagare quando il giocatore è lontano.

DrawMarker deve essere eseguito ogni frame

Un marcatore viene disegnato per un frame ogni volta che chiami DrawMarker. Per mantenerlo sullo schermo lo chiami di nuovo ogni frame, in un loop con 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)

Funziona, ma viene eseguito ogni frame per l'intera sessione, anche quando il giocatore è dall'altra parte della mappa. Correggilo dopo.

Disegna solo quando il giocatore è vicino

Misura la distanza e dormi più a lungo quando il giocatore è lontano. Solo lo stato vicino ha bisogno di 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)

Lontano, il loop si sveglia una volta al secondo e fa una sottrazione. Vicino al marcatore viene eseguito per frame, solo mentre è necessario. Perché questo conta, e come leggerlo in resmon, è in resmon high ms: how to optimize.

Consiglio: #(a - b) è la lunghezza di una differenza di vettore, la distanza. Ha bisogno di valori vec3, che GetEntityCoords restituisce già.

Tipi di marcatore

Il primo argomento è il tipo di marcatore, un numero. Alcuni che i server usano molto:

Tipo Aspetto
1 Un cilindro
2 Una freccia chevron (ruotala di 180 gradi su X per farla puntare giù)
23 Un anello piatto sul terreno
25 Un anello piatto sul terreno, più sottile

L'elenco completo dei tipi è nel sito della documentazione di FiveM, sotto i riferimenti di gioco, marcatori. Gli argomenti di scala cambiano la dimensione, e l'ultimo valore di colore è l'alfa (trasparenza). Posiziona un marcatore sul terreno a z - 1.0 così si siede sul pavimento, non fluttuando alla vita del giocatore.

Help text: il prompt integrato

Il gioco ha un messaggio di aiuto in alto a sinistra dello schermo. Definirai un'etichetta, quindi la visualizzerai ogni frame mentre il giocatore è in portata:

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~ viene sostituito dalla chiave che il giocatore usa per l'azione di contesto, che è E per impostazione predefinita. Chiama showHelp() all'interno del ramo distance < 1.5 sopra, quindi controlla la chiave:

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

Registra l'etichetta una volta in cima al file, non all'interno del loop.

lib.showTextUI e lib.hideTextUI

Con ox_lib puoi mostrare un prompt stilizzato, e lo chiami una sola volta quando il giocatore entra, non ogni frame:

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

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

lib.isTextUIOpen() ti dice se uno è già sullo schermo. Ha bisogno di shared_script '@ox_lib/init.lua' nel tuo manifest (vedi the ox_lib menu guide). Il testo non è legato a una chiave: controlli comunque la chiave tu stesso, o usi un keybind.

Punti di ox_lib: nessun loop di distanza del tutto

Scrivere il loop di distanza a mano per ogni zona si accumula. lib.points lo fa per te: ox_lib controlla la distanza del giocatore a tutti i punti insieme, e esegue solo il tuo codice vicino a loro:

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

Come funziona:

  • onEnter viene eseguito una volta quando il giocatore viene entro la distance.
  • onExit viene eseguito una volta quando lasciano.
  • nearby viene eseguito ogni frame mentre sono dentro la distance, e per niente altrimenti. È dove va DrawMarker.
  • self.currentDistance è la distanza corrente al punto.

Puoi creare centinaia di punti e solo quelli vicini al giocatore costano qualcosa. Rimuovi un punto che non ti serve più con point:remove().

Quale usare

  • Una o due zone: il loop di distanza con un sleep va bene.
  • Molte zone, o uno script che crea zone da config: usa lib.points.
  • Interazioni su oggetti e ped: un target è meglio che un marcatore. Vedi ox_target: how to add targets.

Checklist

Sintomo Soluzione
Il marcatore sfarfalla o appare per un frame Chiama DrawMarker ogni frame in un loop Wait(0)
Lo script costa tempo resmon quando inattivo Dormi 500 a 1000 ms quando lontano, Wait(0) solo quando vicino
Il marcatore fluttua nell'aria Disegnalo a z - 1.0
Il testo del prompt non compare mai Definiscilo con AddTextEntry, quindi visualizzalo ogni frame
lib.showTextUI rimane sullo schermo Chiama lib.hideTextUI() all'uscita
Molte zone sono lente Usa lib.points.new con onEnter, onExit e nearby

Risposte rapide

Perché il mio marcatore scompare dopo un frame?

DrawMarker ha bisogno di essere chiamato ogni frame, in un loop con Wait(0). Chiamalo una volta e appare per un singolo frame.

Perché il mio script usa così tanto tempo resmon?

Un loop Wait(0) che misura la distanza ad ogni marcatore viene eseguito ogni frame tutto il tempo. Dormi più a lungo quando il giocatore è lontano, o usa i punti ox_lib così il loop viene eseguito solo vicino alla zona.

Quale è meglio, help text o lib.showTextUI?

Help text è integrato nel gioco e non ha bisogno di nessuna risorsa. lib.showTextUI è un prompt stilizzato da ox_lib ed è facile mostrare e nascondere dal codice. Scegli uno stile e mantienilo per l'intero server.

Script senza questo problema

Advanced BoostingBoosting di veicoli dal tablet: contratti dalla classe D alla S+, crew e coda in tempo reale.Vedi script →Shop CreatorCrea un negozio in meno di un minuto — proprietari, dipendenti, casseforti e rapine inclusi.Vedi script →Quest CreatorUn editor visuale di missioni e dialoghi con gli NPC, costruito nodo per nodo in gioco.Vedi script →

Continua a leggere