DrawMarker, texto de ayuda y lib.showTextUI sin lag en FiveM

Dibuja marcadores y muestra indicadores «Presiona E» en FiveM sin un bucle pesado: DrawMarker solo cuando esté cerca, natives de texto de ayuda, lib.showTextUI y puntos ox_lib para zonas.

Dibujas un marcador, te acercas a él y parpadea, o nunca se muestra, o tu script se queda en 0.30 ms en resmon sin hacer nada. Los marcadores e indicadores «Presiona E» se ven simples, pero son la fuente clásica de bucles pesados. Este artículo te muestra cómo dibujar un marcador correctamente, cómo mostrar un indicador, y cómo dejar de pagar por ello cuando el jugador está lejos.

DrawMarker tiene que ejecutarse cada fotograma

Un marcador se dibuja durante un fotograma cada vez que llamas a DrawMarker. Para mantenerlo en pantalla lo llamas de nuevo cada fotograma, en un bucle 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)

Eso funciona, pero se ejecuta cada fotograma durante toda la sesión, incluso cuando el jugador está al otro lado del mapa. Arregla eso a continuación.

Solo dibuja cuando el jugador está cerca

Mide la distancia y duerme más cuando el jugador está lejos. Solo el estado cercano necesita 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)

Lejos, el bucle se despierta una vez por segundo y hace una resta. Cerca del marcador se ejecuta por fotograma, solo mientras lo necesita. Por qué esto importa, y cómo leerlo en resmon, está en resmon high ms: how to optimize.

Consejo: #(a - b) es la longitud de una diferencia de vector, la distancia. Necesita valores vec3, que GetEntityCoords ya devuelve.

Tipos de marcadores

El primer argumento es el tipo de marcador, un número. Unos pocos que los servidores usan mucho:

Tipo Se ve como
1 Un cilindro
2 Una flecha de comilla (rótala 180 grados en X para que apunte hacia abajo)
23 Un anillo plano en el suelo
25 Un anillo plano en el suelo, más delgado

La lista completa de tipos está en el sitio de documentación de FiveM, bajo referencias de juego, marcadores. Los argumentos de escala cambian el tamaño, y el último valor de color es el alfa (transparencia). Coloca un marcador de suelo en z - 1.0 para que se asiente en el piso, no flotando en la cintura del jugador.

Texto de ayuda: el indicador integrado

El juego tiene un mensaje de ayuda en la parte superior izquierda de la pantalla. Defines una etiqueta, luego la muestras cada fotograma mientras el jugador esté en rango:

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~ se reemplaza con la tecla que el jugador usa para la acción de contexto, que es E por defecto. Llama a showHelp() dentro de la rama distance < 1.5 anterior, luego comprueba la tecla:

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

Registra la etiqueta una vez en la parte superior del fichero, no dentro del bucle.

lib.showTextUI y lib.hideTextUI

Con ox_lib puedes mostrar un indicador con estilo, y lo llamas una vez cuando el jugador entra, no cada fotograma:

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

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

lib.isTextUIOpen() te dice si ya hay uno en pantalla. Necesita shared_script '@ox_lib/init.lua' en tu manifest (ver the ox_lib menu guide). El texto no está vinculado a una tecla: aún compruebas la tecla tú mismo, u usa un keybind.

Puntos ox_lib: ningún bucle de distancia en absoluto

Escribir el bucle de distancia a mano para cada zona suma. lib.points lo hace por ti: ox_lib comprueba la distancia del jugador a todos los puntos juntos, y solo ejecuta tu código cerca de ellos:

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

Cómo funciona:

  • onEnter se ejecuta una vez cuando el jugador entra dentro de distance.
  • onExit se ejecuta una vez cuando se va.
  • nearby se ejecuta cada fotograma mientras estén dentro de distance, y no en absoluto si no. Ahí es donde va DrawMarker.
  • self.currentDistance es la distancia actual al punto.

Puedes crear cientos de puntos y solo los cerca del jugador cuestan algo. Elimina un punto que ya no necesites con point:remove().

Cuál usar

  • Una o dos zonas: el bucle de distancia con un sleep está bien.
  • Muchas zonas, o un script que crea zonas desde configuración: usa lib.points.
  • Interacciones en objetos y peds: un objetivo es mejor que un marcador. Ver ox_target: how to add targets.

Lista de verificación

Síntoma Solución
El marcador parpadea o se muestra por un fotograma Llama a DrawMarker cada fotograma en un bucle Wait(0)
El script cuesta tiempo de resmon cuando está inactivo Duerme 500 a 1000 ms cuando está lejos, Wait(0) solo cuando esté cerca
El marcador flota en el aire Dibújalo en z - 1.0
El texto del indicador nunca se muestra Defínelo con AddTextEntry, luego muéstralo cada fotograma
lib.showTextUI permanece en pantalla Llama a lib.hideTextUI() al salir
Muchas zonas son lentas Usa lib.points.new con onEnter, onExit y nearby

Respuestas rápidas

¿Por qué mi marcador desaparece después de un fotograma?

DrawMarker tiene que llamarse cada fotograma, en un bucle con Wait(0). Lláma lo una vez y se muestra por un fotograma.

¿Por qué mi script usa tanto tiempo de resmon?

Un bucle Wait(0) que mide la distancia a cada marcador se ejecuta cada fotograma todo el tiempo. Duerme más cuando el jugador está lejos, o usa puntos ox_lib para que el bucle solo se ejecute cerca de la zona.

¿Cuál es mejor, texto de ayuda o lib.showTextUI?

El texto de ayuda está integrado en el juego y no necesita ningún recurso. lib.showTextUI es un indicador con estilo de ox_lib y es fácil de mostrar y ocultar desde el código. Elige un estilo y mantenlo para todo tu servidor.

Scripts que evitan este problema

Advanced BoostingBoosting de vehículos desde una tablet: contratos de clase D a S+, crews y cola en vivo.Ver script →Shop CreatorCrea una tienda en menos de un minuto — dueños, empleados, caja fuerte y atracos.Ver script →Quest CreatorUn editor visual de misiones y diálogos con NPC, nodo a nodo dentro del juego.Ver script →

Sigue leyendo