FiveM NUI ไม่ขึ้น ค้าง หรือเมาส์ติดหน้าจอ แก้อย่างไร

ปัญหา FiveM NUI ไม่ขึ้น, NUI ค้าง, กดเมนูไม่ได้, เปิด Inventory แล้วจอดำ, ปิด Menu แล้วเมาส์ยังติดหน้าจอ หรือเดินไม่ได้หลังปิด UI มักไม่ได้มีต้นเหตุเพียงจุดเดียว เพราะระบบ NUI ของ FiveM มีหลายชั้น ตั้งแต่ Resource, fxmanifest.lua, ui_page, HTML/CSS/JavaScript, SendNUIMessage, NUI Callback ไปจนถึง SET_NUI_FOCUS

FiveM Fullscreen NUI เป็นหน้า UI ที่ Overlay บนเกมและอาจมีหรือไม่มี Input Focus โดย APIs หลักที่เกี่ยวข้องคือ SEND_NUI_MESSAGE และ SET_NUI_FOCUS.

บทความนี้จาก comsiam จะไล่ตรวจแบบเป็นระบบ เพื่อหาว่าปัญหาเกิดที่ Resource, Browser UI, Message, Callback หรือ Focus กันแน่

① แยกอาการ NUI ก่อน

คำว่า NUI พังอาจหมายถึงหลายอาการ

NUI ไม่ขึ้นเลย
NUI ขึ้นแต่เป็นหน้าว่าง
NUI ขึ้นแต่ไม่มีข้อมูล
NUI ขึ้นแต่กดไม่ได้
ปุ่มกดแล้วไม่ทำงาน
NUI ค้าง
ปิด NUI ไม่ได้
เมาส์ติดหน้าจอ
เดินไม่ได้หลังปิด NUI
NUI หายหลัง Restart Resource

แต่ละอาการควรตรวจคนละ Layer

② Flow ของ FiveM NUI

จำ Flow นี้ให้ได้

RESOURCE
↓
fxmanifest.lua
↓
ui_page
↓
HTML / CSS / JS
↓
SendNUIMessage
↓
JavaScript
↓
UI

เวลาผู้เล่นกด Button จะย้อนกลับประมาณ

UI
↓
NUI Callback
↓
Client Script
↓
Server ถ้าจำเป็น

FiveM รองรับ Message จาก Game Script ไปยัง Fullscreen NUI และรองรับ NUI Callbacks สำหรับส่งข้อมูลกลับจาก UI เข้าสู่ Game Script.

③ NUI ไม่ขึ้นเลยให้ตรวจ Resource ก่อน

อย่าเริ่มจาก CSS

ตรวจว่า Resource Start อยู่หรือไม่

เช่น

ensure inventory

หรือ Resource ที่เป็น NUI ของคุณ

ถ้า Resource ไม่ทำงาน client.lua, ui_page และ NUI Logic ภายใน Resource นั้นก็จะไม่เริ่มทำงาน

④ ตรวจ fxmanifest.lua

Resource FiveM ต้องมี Resource Manifest และ fxmanifest.lua ใช้ประกาศ Scripts/Files ที่ Resource ใช้.

ตัวอย่าง

fx_version 'cerulean'
game 'gta5'

client_script 'client.lua'

ui_page 'html/index.html'

files {
'html/index.html',
'html/style.css',
'html/app.js'
}

⑤ ui_page สำคัญอย่างไร

FiveM ใช้

ui_page 'html/index.html'

เพื่อกำหนดหน้า NUI ของ Resource

ถ้าใช้ Local File ตัวหน้า UI และ Dependencies ต้องถูกอ้างใน files.

ดังนั้น Path ผิดเพียงตัวเดียวก็ทำให้ NUI ไม่โหลดตามที่คาด

⑥ ตัวอย่าง ui_page ผิด

Manifest

ui_page 'html/index.html'

แต่ไฟล์จริงอยู่

web/index.html

กรณีนี้ Resource Structure กับ Manifest ไม่ตรงกัน

ให้แก้ Path ก่อนตรวจ JavaScript

⑦ ลืม files ทำให้ NUI พังได้ไหม

ได้

Cfx.re ระบุว่า Local ui_page และ Dependencies ต้องถูกเพิ่มผ่าน files.

เช่น

files {
'html/index.html',
'html/style.css',
'html/app.js',
'html/logo.webp'
}

⑧ HTML ไม่ขึ้นเลยให้ทำ Test Page

เปลี่ยนชั่วคราวเป็น

<!DOCTYPE html>
<html>
<body>
<h1>NUI TEST</h1>
</body>
</html>

ถ้า NUI TEST ยังไม่ขึ้น

ให้เน้น

Resource
fxmanifest
ui_page
files

ก่อน

⑨ HTML ขึ้นแล้วถือว่าแก้อะไรได้บ้าง

ถ้าเห็นข้อความ Test

คุณพิสูจน์ได้อย่างน้อยว่า

Resource
→ ui_page
→ HTML

ทำงานแล้ว

จากนั้นค่อยไปตรวจ

CSS
JavaScript
Message

⑩ CSS ทำให้ NUI ดูเหมือนหายได้ไหม

ได้

เช่น

display: none;

หรือ

visibility: hidden;

หรือ

opacity: 0;

หน้า UI อาจโหลดแล้ว แต่ถูกซ่อนด้วย Style

⑪ Position ผิดก็ทำให้ NUI ดูเหมือนหาย

เช่น

left: -5000px;

หรือ Transform ผิด

transform: translateX(-200vw);

Element ยังอยู่ใน DOM แต่หลุดออกนอกจอ

จึงควรตรวจผ่าน NUI Developer Tools

⑫ เปิด NUI Developer Tools อย่างไร

FiveM มีคำสั่ง

nui_devtools

สำหรับเปิด NUI DevTools จาก Game Process.

ใช้ตรวจ

Console
Elements
CSS
JavaScript
Network
DOM

⑬ F8 กับ NUI DevTools ต่างกันอย่างไร

จำง่าย ๆ

F8
→ FiveM Client / Script

NUI DevTools
→ HTML / CSS / JavaScript

FiveM Client Console มีคำสั่งสำหรับ Debug Resources และ nui_devtools ใช้เปิดเครื่องมือ Debug ของ NUI โดยเฉพาะ.

⑭ JavaScript Error ทำให้ UI ไม่ขึ้นได้ไหม

ได้

เช่น

const menu =
document.getElementById('menu');

menu.classList.remove('hidden');

แต่ Element menu ไม่มีอยู่จริง

JavaScript อาจ Error และ Code ส่วนหลังไม่ทำงาน

เปิด Console ใน NUI DevTools แล้วแก้ Error แรกก่อน

⑮ SendNUIMessage คืออะไร

FiveM มี

SendNUIMessage(data)

สำหรับส่งข้อมูลไปยัง NUI.

ตัวอย่าง

SendNUIMessage({
action = 'open'
})

⑯ ตัวอย่าง Test Message

Client

RegisterCommand('testnui', function()

SendNUIMessage({
action = 'test',
message = 'hello'
})

end)

FiveM รองรับการส่ง Table ผ่าน SendNUIMessage ไปยัง NUI.

⑰ JavaScript รับ Message อย่างไร

ตัวอย่าง

window.addEventListener(
'message',
function(event) {

console.log(
'NUI MESSAGE:',
event.data
);

}
);

Fullscreen NUI ใช้ Browser message Event สำหรับรับข้อมูลจาก Game Script.

⑱ Console ไม่เห็น Message เลย

ตรวจ

Client Script ทำงานไหม
SendNUIMessage ถูกเรียกไหม
Resource ถูกไหม
ui_page โหลดไหม

อย่าแก้ DOM ก่อนพิสูจน์ว่า Message มาถึง Browser

⑲ Message เข้าแต่ UI ไม่เปลี่ยน

แสดงว่า Transport Layer ใช้งานได้แล้ว

ให้ตรวจ

Action Name
JavaScript Condition
DOM Selector
CSS
UI State

แทน

⑳ Action Name ไม่ตรงเป็นปัญหาที่พบบ่อย

Client ส่ง

SendNUIMessage({
action = 'openMenu'
})

แต่ JavaScript ตรวจ

if (
event.data.action
=== 'openmenu'
) {
}

ตัวอักษรไม่ตรง

Logic จึงไม่ทำงาน

㉑ วิธี Debug Action ที่เร็วที่สุด

ก่อนเขียน Condition ซับซ้อน

ใช้

console.log(event.data);

ดูข้อมูลจริงก่อน

แล้วค่อยตรวจ

action
data
state

㉒ NUI ขึ้นแต่ข้อมูลเป็นค่าว่าง

เช่น HUD ขึ้นแต่

Money = undefined
Job = undefined
Health = undefined

ให้ดูชื่อ Property ที่ Client ส่ง

เช่น

SendNUIMessage({
money = 5000
})

JavaScript ต้องอ่าน

event.data.money

ไม่ใช่

event.data.cash

㉓ NUI เปิดแต่คลิกไม่ได้

จุดสำคัญคือ

SET_NUI_FOCUS

FiveM มี SET_NUI_FOCUS(BOOL hasFocus, BOOL hasCursor) สำหรับกำหนด Focus และ Cursor ของ NUI.

㉔ ตัวอย่างเปิด Focus

SetNuiFocus(
true,
true
)

เหมาะกับ UI เช่น

Inventory
Phone
Bank
Menu
Settings

ที่ต้องใช้ Mouse

㉕ HUD จำเป็นต้อง SetNuiFocus ไหม

ถ้า HUD ใช้แสดงข้อมูลอย่างเดียว เช่น

Health
Armor
Speed
Fuel

โดยไม่มี Interaction

ไม่จำเป็นต้องให้ HUD ถือ Mouse/Keyboard Focus

㉖ NUI ขึ้นแต่ Mouse ไม่ขึ้น

ตรวจว่า Code เปิด

SetNuiFocus(
true,
true
)

จริงหรือไม่

Native นี้รับค่าแยกสำหรับ Focus และ Cursor.

㉗ เมาส์ติดหน้าจอหลังปิด NUI

นี่เป็นหนึ่งในอาการยอดนิยมที่สุด

ตอนปิด UI ต้องคืน Focus

SetNuiFocus(
false,
false
)

ถ้าไม่ได้เรียก Focus สามารถค้างจาก State ที่ Resource ตั้งไว้ก่อนหน้าได้ เพราะ IS_NUI_FOCUSED จะคืน Current NUI Focus State ที่เคยตั้งด้วย SET_NUI_FOCUS.

㉘ ตัวอย่าง Close Menu ที่ถูกโครงสร้าง

local menuOpen = false

local function closeMenu()

menuOpen = false

SetNuiFocus(
false,
false
)

SendNUIMessage({
action = 'close'
})

end

ปิดทั้ง

Visual
+
Focus

ไม่ใช่แค่ซ่อน HTML

㉙ CSS display:none ไม่ได้คืน Focus

นี่เป็นจุดที่ผิดบ่อย

JavaScript ทำ

menu.style.display = 'none';

แค่ซ่อน UI

แต่ถ้า Client ยังมี

NUI Focus = true

ผู้เล่นอาจยัง

หมุนกล้องไม่ได้
เดินไม่ได้
เมาส์ค้าง

ต้องคืน Focus ฝั่ง FiveM Script ด้วย

㉚ ตรวจว่า NUI Focus ค้างหรือไม่

FiveM มี

IS_NUI_FOCUSED

ซึ่งคืน Current Focus State.

สำหรับ Debug สามารถตรวจได้ว่าหลัง Close Menu Focus กลับเป็น false หรือยัง

㉛ ตัวอย่าง Debug Focus

RegisterCommand(
'checkfocus',
function()

print(
'NUI focused:',
IsNuiFocused()
)

end
)

ถ้าปิด Menu แล้วค่าเป็น true

Close Flow ยังไม่ Cleanup Focus

㉜ ทำคำสั่งแก้ Mouse ค้างชั่วคราว

สำหรับ Debug

RegisterCommand(
'fixnui',
function()

SetNuiFocus(
false,
false
)

SetNuiFocusKeepInput(
false
)

end
)

นี่ควรใช้เป็น Debug/Fallback ไม่ใช่แทนการแก้ Close Lifecycle

SET_NUI_FOCUS_KEEP_INPUT มีไว้กำหนด Input Behavior ระหว่าง NUI Focus.

㉝ SetNuiFocusKeepInput คืออะไร

FiveM มี

SET_NUI_FOCUS_KEEP_INPUT

รับ Boolean keepInput.

และมี

IS_NUI_FOCUS_KEEPING_INPUT

สำหรับตรวจว่า Keyboard Input ถูกเปิดไว้ระหว่าง NUI Focus หรือไม่.

㉞ เมื่อปิด UI ควร Reset KeepInput ไหม

ถ้า Resource เคยใช้

SetNuiFocusKeepInput(true)

ก็ควรมี Lifecycle ที่คืน State เมื่อ Menu ปิด

เช่น

SetNuiFocusKeepInput(false)
SetNuiFocus(false, false)

เพื่อไม่ให้ Input State ค้างจาก Resource

㉟ NUI ขึ้นแต่เดินได้ทั้งที่ Menu เปิด

ถ้า Resource เปิด Focus พร้อมใช้ KeepInput

Input บางส่วนสามารถถูกออกแบบให้ยังส่งเข้าเกมได้

ตรวจ

SetNuiFocusKeepInput(...)

ก่อนสรุปว่า Focus พัง

FiveM มี Getter สำหรับตรวจ Keep-input State โดยตรง.

㊱ UI หลายตัวแย่ง Focus กันได้ไหม

Fullscreen NUI มี Focus Stack และ Resource ที่ถูก Focus ล่าสุดจะอยู่ด้านบนของ Focus Stack ตามเอกสาร Cfx.re.

ตัวอย่าง Server มี

Inventory
Phone
Bank
HUD Settings
Admin Menu

หลายตัวเปิดพร้อมกัน

อาจเกิด Focus Conflict ได้

㊲ เปิด Inventory แล้ว Phone ใช้ไม่ได้

ตรวจว่า Resource ไหนเรียก

SetNuiFocus

ล่าสุด

เพราะ NUI Focus มี Stack ระหว่าง Fullscreen NUI Resources.

㊳ เปิด Phone แล้ว Inventory หาย

อาจเป็น

UI Visibility Conflict
Focus Stack
NUI State

ไม่ควรแก้ด้วยการเพิ่ม z-index: 9999999 ทันที

CSS z-index กับ NUI Focus Stack เป็นคนละ Layer

㊴ NUI Callback คืออะไร

NUI Callback ใช้ส่งข้อมูลจาก UI กลับเข้าสู่ Game Script

Cfx.re ระบุว่าข้อมูลต้อง JSON-encodable และข้อมูลที่ส่งผ่าน cb จะถูกส่งกลับไปยัง UI.

㊵ ตัวอย่าง Close Callback

Lua

RegisterNUICallback(
'close',
function(data, cb)

SetNuiFocus(
false,
false
)

cb({
ok = true
})

end
)

㊶ ทำไม NUI Callback ต้อง cb

Cfx.re ระบุชัดว่าควร Return Data ผ่าน Callback เสมอ ไม่เช่นนั้น Request จะ Timeout และ Error สามารถย้อนกลับไปยัง fetch ของ UI.

ดังนั้นอย่าเขียน

RegisterNUICallback(
'close',
function(data, cb)

SetNuiFocus(false, false)

-- ไม่มี cb

end
)

㊷ NUI กดปุ่มแล้วหมุนค้างเกิดจาก Callback ได้ไหม

ถ้า JavaScript กำลังรอ Response จาก fetch แต่ Lua Callback ไม่เคยตอบ cb

Request สามารถ Timeout ได้ตาม NUI Callback Documentation.

อาจทำให้ UI Logic ที่รอ Response ไม่เดินต่อ

㊸ Callback Data ต้องเป็นแบบไหน

ข้อมูลรับส่งต้องสามารถ JSON Encode ได้.

ใช้ข้อมูลพื้นฐาน เช่น

string
number
boolean
array
object/table

ที่สามารถ Serialize ได้

㊹ NUI กด Close แต่เมาส์ยังอยู่

ตรวจสองจุด

JavaScript Close ถูกเรียก?
↓
NUI Callback เข้า Lua?
↓
SetNuiFocus(false, false) ถูกเรียก?

อย่าตรวจ CSS อย่างเดียว

㊺ เพิ่ม Log ใน NUI Callback

RegisterNUICallback(
'close',
function(data, cb)

print(
'[NUI] close callback'
)

SetNuiFocus(
false,
false
)

cb({
ok = true
})

end
)

ถ้ากด Close แล้วไม่มี Log

Callback Route ยังไม่เข้าถึง Client Script

㊻ NUI ค้างหลัง Restart Resource

นี่เป็น Lifecycle Problem ที่ควรตรวจ

FiveM มี onClientResourceStart ซึ่งถูกเรียกหลัง Resource เริ่มทำงาน และ onClientResourceStop ถูกเรียกหลัง Resource หยุด.

ใช้ Events เหล่านี้ช่วย Initialize/Cleanup State ได้

㊼ ปัญหา Restart ตอน Menu เปิด

สถานการณ์

Inventory เปิด
↓
NUI Focus = true
↓
Resource ถูก Restart
↓
Close Function ไม่ได้ทำงานตามปกติ

ถ้า Cleanup ไม่ดี ผู้เล่นอาจรู้สึกว่า Input/Focal State ผิดหลัง Restart

จึงควรออกแบบ Resource Stop Handling ไว้

㊽ ตัวอย่าง Cleanup ตอน Resource Stop

AddEventHandler(
'onClientResourceStop',
function(resourceName)

if resourceName
~= GetCurrentResourceName()
then
return
end

SetNuiFocusKeepInput(false)
SetNuiFocus(false, false)

end
)

onClientResourceStop เป็น Client Event ที่ FiveM เรียกหลัง Resource หยุด.

㊾ Start Resource แล้ว NUI State ผิด

ใช้ onClientResourceStart ช่วย Reinitialize

AddEventHandler(
'onClientResourceStart',
function(resourceName)

if resourceName
~= GetCurrentResourceName()
then
return
end

SetNuiFocus(false, false)

SendNUIMessage({
action = 'reset'
})

end
)

onClientResourceStart ถูกเรียกหลัง Resource Start ฝั่ง Client.

㊿ NUI หายหลัง Restart แต่ Focus ยังทำงาน

นี่บอกใบ้ว่า

Browser/UI State

กับ

Focus State

ไม่ Sync กัน

ควรมี State กลาง เช่น

local menuOpen = false

แล้วทุก Open/Close/Restart อ้าง State เดียวกัน

51. อย่าให้หลาย Function เปิด Focus โดยไม่รู้กัน

ตัวอย่าง

openInventory()
openPhone()
openSettings()

ทุกตัวเรียก

SetNuiFocus(true, true)

แต่ Close Function ของตัวหนึ่งเรียก

SetNuiFocus(false, false)

ทั้งที่อีก Menu ยังเปิด

จะเกิด State Conflict ได้

52. ใช้ UI Manager ช่วยได้

Server ที่มีหลาย NUI ควรกำหนด Ownership ชัด

เช่น

Phone
Inventory
Bank
Admin

อย่างน้อยต้องรู้ว่า

Menu ไหนเปิดอยู่
ใครถือ Focus
เมื่อไรคืน Focus

ไม่ควรให้แต่ละ Resource เดาเองทั้งหมด

53. NUI เป็นหน้าขาว

ตรวจ

HTML Path
CSS
JavaScript
External Assets

ถ้า ui_page Local ผิดหรือ Dependencies ไม่อยู่ใน files หน้า UI สามารถโหลดไม่ครบได้ เพราะ Resource Manifest กำหนดให้ Local UI Page และ Dependencies ถูกอ้างใน files.

54. NUI ขึ้นพื้นหลังแต่ไม่มี Menu

แสดงว่า Root Document/CSS บางส่วนอาจโหลดแล้ว

ตรวจ

JavaScript
visibility state
message action

ต่อ

55. เปิด NUI แล้วเห็นเมนูแวบเดียวแล้วหาย

ตรวจ Message Flow

อาจมี

open
↓
close

เข้ามาติดกัน

ใช้

console.log(
Date.now(),
event.data
);

เพื่อดู Sequence จริง

56. NUI เปิดสองครั้งเกิดอะไร

ถ้า Open Event ถูก Trigger ซ้ำ

อาจเกิด

Duplicate State
Duplicate Timer
Duplicate Listener

ถ้า Resource Initialization Register Events ซ้ำหลัง Restart หรือ Character Load

ต้องตรวจ Lifecycle

57. setInterval ซ้ำทำให้ NUI ค้างได้ไหม

ถ้าเปิด Menu ทุกครั้งแล้วสร้าง

setInterval(...)

ใหม่โดยไม่ Clear

Timer สามารถสะสมได้

หลังเปิด/ปิดหลายรอบ UI อาจทำงานซ้ำจำนวนมาก

ควรเก็บ Timer Handle และ Cleanup เมื่อไม่ใช้

58. Event Listener ซ้ำต้องระวัง

อย่า Register

window.addEventListener(
'message',
...
);

ใหม่ทุกครั้งที่เปิด Menu

ถ้า Script File โหลดครั้งเดียว Listener หลักก็ควรสร้างตาม Lifecycle ที่ตั้งใจ

59. NUI ค้างเพราะ Message ถี่เกินไปได้ไหม

SendNUIMessage ใช้ส่งข้อมูลเข้า NUI ทุกครั้งที่ถูกเรียก.

หาก Resource ส่ง

Health
Money
Job
Inventory
Speed
Voice

ซ้ำ ๆ โดยไม่จำเป็น

UI ต้องประมวลผล Messages เพิ่มขึ้น

ควรส่งตาม State/ข้อมูลที่เปลี่ยน

60. UI เปิดแล้ว FPS ลด

ใช้

resmon true

FiveM Resource Monitor จะแสดง CPU และ Memory Usage ของ Resources.

ถ้า Client Resource สูง ให้ตรวจ

Loops
Native Calls
SendNUIMessage

เพิ่มเติม

61. resmon ต่ำแต่ NUI ยังหน่วง

ให้ตรวจ Browser Layer

JavaScript
DOM
CSS Effects
Animation
Large Images

ผ่าน NUI DevTools

เพราะ NUI เป็น HTML-based UI ที่ทำงานบน Chromium Embedded Framework.

62. อย่าใช้ console.log ทุก Frame ใน Production

ระหว่าง Debug ใช้ได้

แต่ถ้า Message เข้ามาถี่มาก

console.log(event.data);

จะสร้าง Console Noise จำนวนมาก

หลังแก้เสร็จควรถอด Log ที่ไม่จำเป็น

63. NUI Focus ควรเปิดทุก Frame ไหม

โดยทั่วไปควรเปลี่ยน Focus เมื่อ State เปลี่ยน เช่น

Menu Open
→ Set Focus

Menu Close
→ Remove Focus

ไม่จำเป็นต้อง Reapply Focus ทุก Frameโดยไม่มีเหตุผล

ให้ State ของ Resource เป็นตัวควบคุม

64. UI เปิดด้วย Key แต่ปิดไม่ได้

ตรวจ

Key Command
NUI Callback
Escape Handler
Close Function

ควรมี Close Path อย่างน้อยหนึ่งทางที่คืน

Visibility
+
Focus

พร้อมกัน

65. ESC ปิด UI แต่ Mouse ยังติด

เป็นอาการชัดว่าฝั่ง Browser ซ่อน UI แล้ว แต่ Client Focus Cleanup ไม่ครบ

ตรวจว่า ESC Handler เรียก NUI Callback กลับ Lua หรือซ่อน DOM อย่างเดียว

66. ตัวอย่าง ESC Close ฝั่ง JavaScript

document.addEventListener(
'keydown',
function(event) {

if (event.key === 'Escape') {

// เรียก callback
// แล้วให้ client เป็นคนคืน focus

}

}
);

หลักสำคัญคืออย่าให้ JavaScript เป็นคนซ่อน UI อย่างเดียว หาก Client ยังถือ NUI Focus

67. NUI ที่ดีควรมี State เดียว

เช่น

local isOpen = false

Open

isOpen = true
SetNuiFocus(true, true)
SendNUIMessage({
action = 'open'
})

Close

isOpen = false
SetNuiFocus(false, false)
SendNUIMessage({
action = 'close'
})

ช่วยลด Visual State กับ Focus State ไม่ตรงกัน

68. วิธี Debug FiveM NUI แบบเร็วที่สุด

ขั้นที่ 1 — ตรวจ Resource

Resource Start หรือไม่

ขั้นที่ 2 — ตรวจ Manifest

fxmanifest.lua
ui_page
files

Local ui_page และ Dependencies ต้องประกาศใน files.

ขั้นที่ 3 — HTML Test

<h1>NUI TEST</h1>

ขั้นที่ 4 — เปิด NUI DevTools

nui_devtools

FiveM มีคำสั่งนี้สำหรับเปิด NUI Dev Tools.

ขั้นที่ 5 — Test SendNUIMessage

SendNUIMessage({
action = 'test'
})

ขั้นที่ 6 — Log Message

console.log(event.data);

ขั้นที่ 7 — ถ้าคลิกไม่ได้

ตรวจ

SET_NUI_FOCUS

ขั้นที่ 8 — ถ้าเมาส์ค้าง

ตรวจ

IS_NUI_FOCUSED
SET_NUI_FOCUS_KEEP_INPUT

ขั้นที่ 9 — ถ้าปุ่ม Callback ค้าง

ตรวจว่า cb ถูกตอบทุกครั้ง.

ขั้นที่ 10 — ถ้าพังหลัง Restart

ตรวจ onClientResourceStart และ onClientResourceStop.

69. ตารางสรุป NUI มีปัญหา

อาการจุดที่ควรตรวจ
NUI ไม่ขึ้นResource / ui_page
HTML ไม่โหลดfiles / Path
NUI หน้าขาวHTML / JS / Assets
UI ขึ้นแต่ข้อมูลไม่มีSendNUIMessage
Message เข้าแต่ UI ไม่เปลี่ยนJavaScript / DOM
UI ขึ้นแต่คลิกไม่ได้SET_NUI_FOCUS
Mouse ไม่ขึ้นCursor Focus
Mouse ค้างหลังปิดFocus Cleanup
เดินไม่ได้หลังปิดFocus/Keep Input
Callback กดแล้วค้างไม่ตอบ cb
UI แวบแล้วหายState/Open-Close Messages
Restart แล้ว NUI พังResource Lifecycle
NUI เปิดซ้ำDuplicate Events
UI หน่วงJS/DOM/Message Frequency
Resource CPU สูงClient Loop / resmon

70. Checklist FiveM NUI

☐ Resource Started
☐ fxmanifest.lua ถูก
☐ ui_page ถูก
☐ files ครบ
☐ HTML โหลด
☐ CSS โหลด
☐ JavaScript ไม่มี Error
☐ SendNUIMessage ทำงาน
☐ Message Listener ทำงาน
☐ Action Names ตรงกัน
☐ SetNuiFocus ตอนเปิดถูก
☐ SetNuiFocus ตอนปิดถูก
☐ KeepInput ถูก
☐ Callback ทำงาน
☐ Callback ตอบ cb
☐ Resource Stop Cleanup ถูก
☐ Resource Start Reset ถูก
☐ ไม่มี Duplicate Listener
☐ ไม่มี Duplicate Timer
☐ resmon ไม่สูงผิดปกติ

71. ตัวอย่าง NUI Open/Close แบบครบ

local isOpen = false

local function openMenu()

if isOpen then
return
end

isOpen = true

SetNuiFocus(
true,
true
)

SetNuiFocusKeepInput(
false
)

SendNUIMessage({
action = 'open'
})

end

local function closeMenu()

if not isOpen then
return
end

isOpen = false

SetNuiFocusKeepInput(
false
)

SetNuiFocus(
false,
false
)

SendNUIMessage({
action = 'close'
})

end

SET_NUI_FOCUS ใช้กำหนด Focus/Cursor ส่วน SET_NUI_FOCUS_KEEP_INPUT ควบคุม Input Behavior ระหว่าง NUI Focus.

72. ตัวอย่าง NUI Callback Close

RegisterNUICallback(
'close',
function(data, cb)

closeMenu()

cb({
ok = true
})

end
)

NUI Callback ควรตอบ cb เสมอเพื่อไม่ให้ Request Timeout.

73. ตัวอย่าง Cleanup เมื่อ Resource Stop

AddEventHandler(
'onClientResourceStop',
function(resourceName)

if resourceName
~= GetCurrentResourceName()
then
return
end

SetNuiFocusKeepInput(false)
SetNuiFocus(false, false)

end
)

FiveM เรียก onClientResourceStop หลัง Client Resource หยุด จึงใช้เป็นจุด Cleanup ได้.

74. ตัวอย่าง Reset ตอน Resource Start

AddEventHandler(
'onClientResourceStart',
function(resourceName)

if resourceName
~= GetCurrentResourceName()
then
return
end

SetNuiFocusKeepInput(false)
SetNuiFocus(false, false)

SendNUIMessage({
action = 'reset'
})

end
)

onClientResourceStart ถูกเรียกหลัง Resource เริ่มทำงานฝั่ง Client.

75. อย่าแก้ Mouse ค้างด้วย Restart FiveM อย่างเดียว

Restart Client อาจทำให้ State หายชั่วคราว

แต่ถ้า Resource ยังมี

Open
→ SetNuiFocus(true,true)

Close
→ ไม่คืน Focus

ปัญหาจะกลับมาอีก

ต้องแก้ Close Lifecycle

76. อย่าซ่อน NUI อย่างเดียว

การทำ

document.body.style.display =
'none';

ไม่ได้หมายความว่า FiveM คืน Focus แล้ว

ต้องแยก

Visual State

กับ

Input Focus State

ออกจากกัน

77. อย่าใส่ SetNuiFocus(false,false) ทุก Frame

การแก้ Focus Conflict ควรทำจาก Event/State ที่ชัด

เช่น

Menu Close
Resource Stop
Emergency Recovery

ไม่ใช่ Loop ที่บังคับคืน Focus ตลอดเวลา เพราะ Resource อื่นอาจต้องใช้ NUI Focus อยู่

78. อย่าล้าง Cache เป็นขั้นตอนแรก

ถ้าต้นเหตุคือ

ui_page ผิด
Callback ไม่ตอบ cb
SetNuiFocus ไม่คืน
JavaScript Error

การล้าง FiveM Cache ไม่แก้ Root Cause เหล่านี้

Debug Resource ก่อน

79. อย่าเปลี่ยน NUI Resource ทั้งตัวทันที

ถ้า UI

เปิดได้
แต่ Mouse ค้าง

ปัญหาอาจเป็น Code เพียงบรรทัดเดียวใน Close Flow

ไม่จำเป็นต้องเปลี่ยน Inventory/HUD/Phone Resource ใหม่ทั้งระบบ

80. สูตรจำง่ายเมื่อ NUI พัง

PAGE
↓
MESSAGE
↓
JAVASCRIPT
↓
CALLBACK
↓
FOCUS
↓
CLEANUP

ถ้าแยกหกชั้นนี้ได้ การหาปัญหา NUI จะเร็วขึ้นมาก

สรุป FiveM NUI ไม่ขึ้น ค้าง หรือเมาส์ติดหน้าจอ แก้อย่างไร

ถ้า FiveM NUI ไม่ขึ้นเลย ให้เริ่มจาก

Resource
↓
fxmanifest.lua
↓
ui_page
↓
files
↓
HTML

ก่อน เพราะ FiveM กำหนด NUI Page ผ่าน ui_page และถ้าใช้ Local Files หน้า UI พร้อม Dependencies ต้องถูกอ้างใน files.

ถ้า HTML ขึ้นแต่ไม่มีข้อมูล ให้ตรวจ SendNUIMessage และ Browser message Listener เพราะ FiveM ใช้ Message Flow นี้ส่งข้อมูลจาก Game Script ไปยัง Fullscreen NUI.

ถ้า Message เข้ามาแล้วแต่ NUI ยังไม่เปลี่ยน ให้เปิด

nui_devtools

จาก F8 แล้วตรวจ JavaScript, DOM และ CSS โดยตรง เพราะ FiveM มีคำสั่งนี้สำหรับเปิด NUI Developer Tools.

ถ้า NUI เปิดแต่คลิกไม่ได้หรือ Mouse ไม่ขึ้น ให้ตรวจ SET_NUI_FOCUS ซึ่งใช้กำหนด Focus และ Cursor ของ NUI.

ถ้า ปิด NUI แล้ว Mouse ยังติดหน้าจอหรือเดินไม่ได้ ให้ตรวจว่ามี

SetNuiFocus(false, false)

และหาก Resource ใช้ SET_NUI_FOCUS_KEEP_INPUT ก็ควรคืน State นั้นด้วย โดย FiveM มี IS_NUI_FOCUSED และ IS_NUI_FOCUS_KEEPING_INPUT สำหรับตรวจ Current State.

ถ้า กด Button แล้ว UI ค้าง ให้ตรวจ NUI Callback เพราะ Cfx.re ระบุว่าต้อง Return ข้อมูลผ่าน cb; ถ้าไม่ตอบ Request จะ Timeout และ Error จะย้อนกลับไปยัง fetch ฝั่ง UI.

ถ้า NUI พังหลัง Restart Resource ให้เพิ่ม Lifecycle Cleanup ผ่าน onClientResourceStop และ Initialization ผ่าน onClientResourceStart เพื่อให้ Focus/UI State กลับสู่สถานะที่ถูกต้องเมื่อ Resource หยุดหรือเริ่มใหม่.

ถ้า NUI หน่วงหรือ FPS ลด ให้ใช้ resmon true ตรวจ CPU/Memory ของ Resource แล้วเปิด NUI DevTools ตรวจ JavaScript/DOM ต่อ เพราะ Resource Monitor ของ FiveM มีไว้ช่วยตรวจ Performance ของ Resources ระหว่าง Gameplay.

แนวทางของ comsiam คือ Debug NUI ตามลำดับ Resource → Page → Message → JavaScript → Callback → Focus → Cleanup อย่าล้าง Cache หรือเปลี่ยน Resource ก่อนรู้ว่า Layer ไหนเสีย เพราะปัญหาอย่าง “เมาส์ติดหน้าจอ” หลายครั้งไม่ได้เกิดจาก NUI ทั้งระบบ แต่เกิดจาก Resource ซ่อน Interface แล้วลืมคืน SET_NUI_FOCUS เพียงจุดเดียว

Comments

Popular posts from this blog

FiveM ยังน่าเล่นไหม? Enhanced เปลี่ยน FiveM แค่ไหน

FiveM คืออะไร เล่นอย่างไร สำหรับมือใหม่ เริ่มต้นตั้งแต่ศูนย์

วิธีตั้ง Admin Permission ด้วย add_ace และ add_principal FiveM แบบละเอียด