Cursor FiveM preso ou não pode se mover após fechar um menu: correção de foco NUI
Cursor preso na tela ou não pode se mover após fechar um menu? Como SetNuiFocus funciona, fechando com um retorno de chamada NUI, tratando ESC em JavaScript e encontrando o culpado.
Você fecha um menu, e uma destas coisas acontece:
the mouse cursor stays on screen
the character will not move or look around
the keyboard does nothing until you reconnectNada aparece no console, porque nada está errado com o código que funciona: ele apenas nunca devolveu o foco. Aqui está como o foco funciona, como fechar um menu corretamente e como encontrar o culpado.
Como o foco NUI funciona
Uma NUI é uma página web (HTML, CSS e JavaScript) que FiveM desenha sobre o jogo. Enquanto tem foco, mouse e teclado vão para a página em vez do jogo. Um script dá e tira foco com um nativo:
SetNuiFocus(hasFocus, hasCursor)SetNuiFocus(true, true): a NUI recebe o teclado e o mouse, e o cursor aparece.SetNuiFocus(true, false): a NUI recebe o teclado, sem cursor.SetNuiFocus(false, false): o foco volta para o jogo e o cursor se esconde.
Se um menu abre com true, true e nenhum código jamais chama SetNuiFocus(false, false), o jogo fica travado, mesmo se a página estiver oculta.
A correção: sempre feche com SetNuiFocus(false, false)
Coloque o fechamento em uma função e use-a para cada maneira de fechar o menu:
local open = false
local function openMenu()
open = true
SetNuiFocus(true, true)
SendNUIMessage({ action = 'open' })
end
local function closeMenu()
open = false
SetNuiFocus(false, false)
SendNUIMessage({ action = 'close' })
endFaça o mesmo se o menu pode ser fechado por outro código: quando o jogador morre, entra em um veículo, ou quando o recurso para.
AddEventHandler('onResourceStop', function(resource)
if resource == GetCurrentResourceName() and open then
SetNuiFocus(false, false)
end
end)Este último importa. Se um recurso para enquanto seu menu está aberto, o foco não é devolvido para você, e o jogador fica preso até se reconectar.
Feche da página: RegisterNUICallback e fetch
Um botão de fechamento, ou um pressionamento de tecla dentro da página, funciona em JavaScript. JavaScript não pode chamar um nativo, então envia uma solicitação para o lado Lua, que a manipula:
RegisterNUICallback('close', function(data, cb)
closeMenu()
cb('ok')
end)Em sua página, envie a solicitação com fetch para https://<resource name>/close. GetParentResourceName() lhe dá o nome do recurso dentro de uma página NUI:
function closeMenu() {
fetch(`https://${GetParentResourceName()}/close`, {
method: 'POST',
headers: { 'Content-Type': 'application/json; charset=UTF-8' },
body: JSON.stringify({}),
})
}
document.getElementById('close-button').addEventListener('click', closeMenu)O retorno de chamada deve chamar cb. Se nunca responder, a solicitação na página fica aberta, e algumas bibliotecas param de esperar por ela. Sempre termine um retorno de chamada com cb('ok') ou outra resposta.
ESC e outras teclas em JavaScript
Enquanto a NUI tem foco, o jogo não vê o teclado, então a tecla ESC nunca chega ao seu código Lua. A página tem que escutá-la:
window.addEventListener('keydown', (event) => {
if (event.key === 'Escape') {
closeMenu()
}
})Adicione a mesma verificação para qualquer outra tecla que deve fechar o menu. Se a página tem uma caixa de entrada, pense no que a tecla faz lá: ESC em um campo de texto ainda deve fechar o menu, mas uma letra não deve.
Atenção: não confie apenas em um botão de fechamento. Se um jogador pressiona ESC e a página não tem um listener, o menu de pausa pode abrir, e o menu fica na tela sem nenhuma maneira de fechá-lo.
Caminhar enquanto um menu está aberto
Algumas interfaces, como um HUD com um pequeno painel ou um telefone, devem deixar o jogador continuar se movendo. Para isso use SetNuiFocusKeepInput:
SetNuiFocus(true, true)
SetNuiFocusKeepInput(true)Com entrada mantida, o jogo ainda recebe o teclado enquanto a NUI tem foco. Se você o ativar, desligue quando o menu fecha, porque fica ligado até você fazer:
local function closeMenu()
SetNuiFocusKeepInput(false)
SetNuiFocus(false, false)
endUm SetNuiFocusKeepInput(true) restante dá sintomas estranhos: o cursor desaparece mas algumas teclas se comportam de forma estranha ou não fazem nada.
Encontre o recurso que segura o foco
Frequentemente o menu preso não é seu. Quando você não sabe qual recurso pegou o foco, encontre-o por eliminação:
- Reproduza o problema: abra o menu, feche-o, e veja o cursor preso.
- No console do servidor (ou no Console ao Vivo do txAdmin), digite
restart resource_namepara um recurso que tem um menu: um telefone, inventário, loja, menu radial ou menu de roupas. - Verifique se o cursor e os controles voltam ou se o problema não acontece mais.
- Repita para o próximo recurso até que o comportamento mude.
Quando uma reinicialização devolve o foco, esse script o segura. Procure em seu código por um caminho de fechamento que não chame SetNuiFocus(false, false): um erro antes da linha de fechamento, uma morte ou uma mudança de trabalho que fecha apenas o HTML, ou um retorno de chamada que não responde. Um erro no console no momento do bug é uma dica forte: veja como ler um erro de script FiveM.
Se é um script que você comprou, envie ao seu autor os passos exatos e o nome do recurso que você encontrou.
Lista de verificação
| Sintoma | Solução |
|---|---|
| Cursor fica após fechar | Chame SetNuiFocus(false, false) na função de fechamento |
| Botão de fechamento não faz nada | Adicione RegisterNUICallback('close', ...) e um fetch para https://<resource>/close |
| ESC não fecha o menu | Escute Escape em JavaScript e chame o retorno de chamada de fechamento |
| Preso após reinicialização de recurso | Libere o foco em onResourceStop |
| Personagem não pode se mover após fechar | Desligue SetNuiFocusKeepInput(false) ao fechar |
| Não sabe qual script faz isso | Reinicie recursos um por um até que o cursor volte |
| Retorno de chamada trava | Sempre responda com cb('ok') |
Respostas rápidas
Por que meu cursor fica na tela após eu fechar um menu?
O menu ocultou seu HTML, mas nada disse ao jogo para devolver o foco. O script tem que chamar SetNuiFocus(false, false) quando o menu fecha.
O que SetNuiFocusKeepInput faz?
SetNuiFocusKeepInput(true) permite que o jogo receba entrada de teclado enquanto uma NUI tem foco, para que o jogador ainda possa caminhar. Deve ser desligado novamente quando o menu fecha.
Como encontro qual recurso mantém o foco?
Reinicie seus recursos um de cada vez e verifique após cada um se o cursor e os controles voltam. Aquele cuja reinicialização o corrige é aquele que mantém o foco.
Scripts sem esse problema
Mic PhoneUm celular dobrável que abre em tablet e chega ao celular de verdade do jogador.Ver script →
Arcade MachinesSete jogos de fliperama jogáveis em máquinas de verdade, com rankings e apostas.Ver script →
Clothing DesignerCrie roupas dentro do FiveM — pincel, camadas, importação de imagens e IA — e vista na hora.Ver script →