Zonas de ox_lib: lib.zones.box, sphere y poly con onEnter y onExit

Cómo usar zonas de ox_lib en FiveM: lib.zones.box, sphere y poly con coords, tamaño, rotación y debug, onEnter, onExit, inside, eliminando zonas, y ox_target.

Necesitas saber cuándo un jugador entra en una tienda, un garaje o un área restringida, sin verificar la distancia en un bucle cada fotograma. Las zonas de ox_lib lo hacen por ti: describes una forma, y llama tu función cuando el jugador entra o sale. Esta guía cubre las tres formas, los callbacks, eliminación y cuándo usar ox_target en su lugar.

Las zonas necesitan ox_lib como dependencia, cargada con @ox_lib/init.lua. Si falta, véase ox_lib init.lua not found.

Tipos de zona

Hay tres, todas bajo lib.zones y todas del lado del cliente.

Box, un rectángulo con altura, bueno para habitaciones y puertas:

lua
local zone = lib.zones.box({
    coords = vec3(441.0, -981.0, 30.7),
    size = vec3(4.0, 6.0, 3.0),
    rotation = 90.0,
    debug = true,
    onEnter = function(self)
        print('entered the box')
    end,
    onExit = function(self)
        print('left the box')
    end,
})

Sphere, un radio alrededor de un punto, bueno para áreas abiertas:

lua
local zone = lib.zones.sphere({
    coords = vec3(441.0, -981.0, 30.7),
    radius = 3.0,
    debug = true,
    onEnter = function() print('in range') end,
    onExit = function() print('out of range') end,
})

Poly, un contorno de puntos para formas irregulares como un patio o un estacionamiento:

lua
local zone = lib.zones.poly({
    points = {
        vec3(400.0, -1000.0, 29.0),
        vec3(420.0, -1000.0, 29.0),
        vec3(420.0, -970.0, 29.0),
        vec3(400.0, -970.0, 29.0),
    },
    thickness = 4.0,
    debug = true,
    onEnter = function() print('in the yard') end,
    onExit = function() print('left the yard') end,
})

Para un poly, thickness es qué tan alta es la forma alrededor de la altura de los puntos. Mantén los puntos al nivel del suelo y el grosor lo suficientemente grande como para incluir jugadores en escaleras.

Coords, tamaño y rotación

  • coords es el centro de una caja o esfera. Obtén con GetEntityCoords(PlayerPedId()) mientras estás de pie allí, o desde una herramienta de coordenadas.
  • size para una caja es ancho, largo y alto como un vec3, centrado en coords.
  • rotation gira la caja alrededor de su eje vertical, en grados. Usa el encabezado del edificio o puerta.
  • radius es para esferas.

La forma más fácil de acertar debug = true: la zona se dibuja en el mundo, para que puedas caminar a través de ella, cambiar un número e reiniciar el recurso hasta que encaje. Apaga debug antes del lanzamiento, ya que dibuja cada fotograma.

Callbacks: onEnter, onExit, inside

Tres callbacks cubren los casos:

lua
local zone = lib.zones.sphere({
    coords = vec3(441.0, -981.0, 30.7),
    radius = 4.0,
    onEnter = function(self)
        lib.showTextUI('[E] Open shop')
    end,
    onExit = function(self)
        lib.hideTextUI()
    end,
    inside = function(self)
        if IsControlJustReleased(0, 38) then
            print('pressed E inside the zone')
        end
    end,
})
  • onEnter y onExit se ejecutan una vez por cruce. Úsalos para notificaciones, UI de texto, cargando o descargando algo.
  • inside se ejecuta cada tick mientras el jugador está dentro. Cualquier cosa que deba verificarse cada fotograma, como una pulsación de tecla, va aquí, y nada fuera de la zona te cuesta.

Mantén inside corto: sin llamadas a base de datos, sin lib.callback.await, sin Wait en un bucle. Para el detalle de pulsación de tecla, véase markers and text UI.

Eliminando zonas

lib.zones.box devuelve un objeto. Mantenlo y elimínalo cuando el área deje de importar:

lua
local shopZone

local function createZone()
    shopZone = lib.zones.box({
        coords = vec3(441.0, -981.0, 30.7),
        size = vec3(4.0, 4.0, 3.0),
        onEnter = function() lib.showTextUI('[E] Shop') end,
        onExit = function() lib.hideTextUI() end,
    })
end

local function removeZone()
    if shopZone then
        shopZone:remove()
        shopZone = nil
    end
end

AddEventHandler('onResourceStop', function(resource)
    if resource == GetCurrentResourceName() then
        removeZone()
        lib.hideTextUI()
    end
end)

Recuerda ocultar cualquier UI que la zona estaba mostrando: si el jugador está adentro cuando la eliminas, onExit puede no ser llamado para ellos.

También puedes preguntarle a una zona si un punto está dentro de ella, con zone:contains(coords), por ejemplo para verificar la posición del jugador cuando se abre un menú.

Zonas vs ox_target

Resuelven diferentes problemas:

lib.zones ox_target
Pregunta "¿Está el jugador en esta área?" "¿Está el jugador mirando esto y presionando un botón?"
Salida Tus callbacks Una lista de opciones en el menú de objetivo
Usar para Zonas seguras, límites de velocidad, áreas de música, generando NPCs cuando está cerca Puertas, cajeros automáticos, mostradores de tienda, objetos

Si el jugador debe elegir interactuar, usa ox_target zones, y compáralo con sistemas más antiguos en qb-target vs ox-target. Si algo debe suceder automáticamente cuando llegan, usa una zona lib. Combinarlos es común: una zona carga un ped cuando llegas, y ox_target le da opciones al ped.

Rendimiento

Las zonas son baratas en comparación con un bucle manual #(coords - playerCoords) < 3.0, porque ox_lib las verifica en un bucle central y solo ejecuta tu función inside donde aplica. Algunos hábitos lo mantienen de esa manera:

  • Crea zonas una vez, no en un bucle o cada vez que se abre un menú.
  • No crees cientos de zonas diminutas si una más grande sería suficiente.
  • Pon el trabajo en onEnter y onExit en lugar de inside.
  • Apaga debug en producción.

Verifica el resultado con resmon, como en high resmon ms.

Lista de verificación

Síntoma Solución
La zona nunca se dispara Usa el centro coords, el size y rotation correcto; establece debug = true para verla
lib es nil Añade @ox_lib/init.lua a shared_scripts
La UI de texto permanece después de dejar Llama a lib.hideTextUI() en onExit y cuando se elimina la zona
La pulsación de tecla no se detecta Veríficala en inside, no en onEnter
El reinicio del recurso deja zonas atrás Llama a zone:remove() en onResourceStop
Alto resmon Mantén inside ligero y deshabilita debug

Respuestas rápidas

¿Cuál es la diferencia entre lib.zones y ox_target?

lib.zones te dice cuándo el jugador está dentro de un área, así que ejecutas tu propio código. ox_target añade una interacción (una opción de mirar y hacer clic) a una entidad o zona. Usa zonas para áreas, ox_target para cosas que el jugador presiona.

¿Cómo muestro una zona mientras la construyo?

Establece debug = true en las opciones de zona. Dibuja la forma en el mundo, para que puedas corregir coordenadas, tamaño y rotación. Apágalo cuando termines.

¿Cómo elimino una zona?

Mantén el objeto que devuelve lib.zones.box y llama a zone:remove(). Hazlo cuando se detiene el recurso o cuando el área ya no es necesaria.

Scripts que evitan este problema

Shop CreatorCrea una tienda en menos de un minuto — dueños, empleados, caja fuerte y atracos.Ver script →Advanced BoostingBoosting de vehículos desde una tablet: contratos de clase D a S+, crews y cola en vivo.Ver script →CCTV Security CamerasCámaras colocables, una tablet con vista múltiple en vivo y fotos como prueba.Ver script →

Sigue leyendo