Zonas ox_lib: lib.zones.box, sphere e poly com onEnter e onExit

Como usar zonas ox_lib em FiveM: lib.zones.box, sphere e poly com coords, size, rotation e debug, onEnter, onExit, inside, removendo zonas e ox_target.

Você precisa saber quando um jogador entra em uma loja, garagem ou área restrita, sem verificar a distância em um loop a cada quadro. Zonas ox_lib fazem isso para você: você descreve uma forma e ela chama sua função quando o jogador entra ou sai. Este guia cobre as três formas, os retornos de chamada, remoção e quando usar ox_target em vez disso.

Zonas precisam ox_lib como dependência, carregadas com @ox_lib/init.lua. Se estiver faltando, veja ox_lib init.lua não encontrado.

Tipos de zona

Há três, todos em lib.zones e todos do lado do cliente.

Box, um retângulo com uma altura, bom para salas e portas:

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, um raio ao redor de um ponto, bom para áreas abertas:

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, um contorno de pontos para formas irregulares como um pátio ou estacionamento:

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 um poly, thickness é o quão alto a forma é ao redor da altura dos pontos. Mantenha os pontos no nível do solo e a espessura grande o suficiente para incluir jogadores em escadas.

Coords, tamanho e rotação

  • coords é o centro de uma box ou sphere. Obtenha com GetEntityCoords(PlayerPedId()) enquanto está lá, ou de uma ferramenta de coordenada.
  • size para uma box é largura, comprimento e altura como um vec3, centrado em coords.
  • rotation gira a box ao redor de seu eixo vertical, em graus. Use o heading do edifício ou porta.
  • radius é para spheres.

A maneira mais fácil de acertar esses é debug = true: a zona é desenhada no mundo, para que você possa caminhar, mudar um número e reiniciar o recurso até se adequar. Desligue debug antes da versão, já que desenha a cada quadro.

Retornos de chamada: onEnter, onExit, inside

Três retornos de chamada cobrem os 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 e onExit rodam uma vez por travessia. Use-os para notificações, UI de texto, carregamento ou descarregamento de algo.
  • inside roda a cada tick enquanto o jogador está dentro. Qualquer coisa que deve ser verificada cada quadro, como um pressionamento de tecla, vai aqui, e nada fora da zona custa.

Mantenha inside curto: sem chamadas de banco de dados, sem lib.callback.await, sem Wait em um loop. Para o detalhe de pressionamento de tecla, veja marcadores e UI de texto.

Removendo zonas

lib.zones.box retorna um objeto. Mantenha e remova quando a área para 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)

Lembre-se de esconder qualquer UI que a zona estava mostrando: se o jogador estiver dentro quando você a remove, onExit pode não ser chamado para eles.

Você também pode perguntar a uma zona se um ponto está dentro dela, com zone:contains(coords), por exemplo para verificar a posição do jogador quando um menu abre.

Zonas vs ox_target

Eles resolvem problemas diferentes:

lib.zones ox_target
Pergunta "O jogador está nesta área?" "O jogador está olhando para isto e pressionando um botão?"
Saída Seus retornos de chamada Uma lista de opções no menu de alvo
Use para Zonas seguras, limites de velocidade, áreas de música, aparecimento de NPCs quando perto Portas, caixas eletrônicos, balcões de loja, objetos

Se o jogador deve escolher interagir, use zonas ox_target e compare com sistemas mais antigos em qb-target vs ox-target. Se algo deve acontecer automaticamente quando chegam, use uma zona lib. Combiná-los é comum: uma zona carrega um ped quando você chega, e ox_target dá ao ped suas opções.

Performance

Zonas são baratas em comparação com um loop manual #(coords - playerCoords) < 3.0, porque ox_lib as verifica em um loop central e apenas executa sua função inside onde se aplica. Alguns hábitos mantêm assim:

  • Crie zonas uma vez, não em um loop ou cada vez que um menu abre.
  • Não crie centenas de zonas minúsculas se uma única maior funcionaria.
  • Coloque o trabalho em onEnter e onExit em vez de inside.
  • Desligue debug em produção.

Verifique o resultado com resmon, como em resmon ms alto.

Lista de verificação

Sintoma Solução
Zona nunca dispara Use as coords do centro, o size e rotation corretos; defina debug = true para vê-lo
lib é nil Adicione @ox_lib/init.lua a shared_scripts
UI de texto fica após sair Chame lib.hideTextUI() em onExit e quando a zona é removida
Pressionamento de tecla não detectado Verifique em inside, não onEnter
Reinicialização de recurso deixa zonas para trás Chame zone:remove() em onResourceStop
Resmon alto Mantenha inside leve e desabilite debug

Respostas rápidas

Qual é a diferença entre lib.zones e ox_target?

lib.zones lhe diz quando o jogador está dentro de uma área, então você executa seu próprio código. ox_target adiciona uma interação (uma opção de mirar e clicar) a uma entidade ou zona. Use zonas para áreas, ox_target para coisas que o jogador pressiona.

Como mostro uma zona enquanto a construo?

Defina debug = true nas opções da zona. Desenha a forma no mundo, para que você possa corrigir coordenadas, tamanho e rotação. Desligue quando terminar.

Como removo uma zona?

Mantenha o objeto que lib.zones.box retorna e chame zone:remove(). Faça-o quando o recurso para ou quando a área não for mais necessária.

Scripts sem esse problema

Shop CreatorMonte uma loja em menos de um minuto — donos, funcionários, cofres e assaltos inclusos.Ver script →Advanced BoostingBoosting de veículos pelo tablet: contratos da classe D à S+, crews e fila ao vivo.Ver script →CCTV Security CamerasCâmeras posicionáveis, um tablet com várias telas ao vivo e fotos impressas como prova.Ver script →

Continue lendo