FiveM NUI คืออะไร วิธีสร้าง UI ด้วย HTML CSS JavaScript แบบละเอียด

FiveM NUI คือระบบ User Interface แบบ HTML ของ CitizenFX/FiveM ที่ช่วยให้ผู้พัฒนาสร้างหน้าต่างและ Interface ภายในเกมด้วยเทคโนโลยีเว็บ เช่น HTML, CSS และ JavaScript แทนการจำกัดอยู่เฉพาะ HUD หรือ UI ดั้งเดิมของ GTA V โดย Cfx.re ระบุว่า NUI ย่อมาจาก New UI และปัจจุบันทำงานผ่าน Chromium Embedded Framework พร้อมรองรับ Web Frameworks อย่าง React หรือ Angular และ WebGL ได้ด้วย.

NUI ถูกนำไปใช้กับระบบจำนวนมาก เช่น

HUD
Inventory
Phone
Banking
Garage
Character Menu
Job Menu
Vehicle Menu
Scoreboard
Settings
Shop
Admin Menu
Loading Screen

บทความนี้จาก comsiam จะอธิบายตั้งแต่โครงสร้าง NUI, fxmanifest.lua, ui_page, SendNUIMessage, NUI Callback, SET_NUI_FOCUS, JavaScript Message, DUI ไปจนถึง Security และแนวทาง Optimize NUI สำหรับ Server จริง

① FiveM NUI คืออะไร

NUI คือระบบสร้าง User Interface ภายใน FiveM ด้วย Web Technologies

โครงสร้างพื้นฐานคือ

FiveM Script
↓
NUI
↓
HTML
CSS
JavaScript
↓
Interface บนหน้าจอ

Cfx.re อธิบายว่า NUI เป็น HTML-based UI Functionality ของ CitizenFX Framework และ Fullscreen NUI สามารถ Overlay อยู่เหนือ Game View ได้.

② NUI ย่อมาจากอะไร

NUI ย่อมาจาก

New UI

ตาม Documentation ของ Cfx.re.

อย่างไรก็ตามในงาน FiveM ปัจจุบันคำว่า NUI มักถูกใช้หมายถึงระบบ HTML-based UI ทั้งชุด

③ NUI ใช้อะไรสร้าง

พื้นฐานคือ

HTML
CSS
JavaScript

และ Cfx.re ระบุว่าสามารถใช้ Framework หรือ Technology ฝั่งเว็บเพิ่มเติมได้ เช่น React, Angular และ accelerated WebGL.

④ HTML ทำหน้าที่อะไร

HTML เป็นโครงสร้างของ Interface

ตัวอย่าง

<div id="inventory">
<h1>Inventory</h1>

<div id="items"></div>
</div>

เปรียบเสมือนโครงกระดูกของ UI

⑤ CSS ทำหน้าที่อะไร

CSS ใช้ควบคุม

ตำแหน่ง
ขนาด
สี
Font
Animation
Responsive Layout
Opacity
Transition

ตัวอย่าง

#inventory {
position: absolute;
width: 600px;
height: 700px;

top: 50%;
left: 50%;

transform:
translate(-50%, -50%);
}

เพราะ NUI เป็น Web UI จึงสามารถใช้ CSS Layout Techniques แบบเว็บได้.

⑥ JavaScript ทำหน้าที่อะไร

JavaScript ใช้ควบคุม Logic ฝั่ง Interface เช่น

เปิด Menu
ปิด Menu
อัปเดตข้อมูล
กด Button
ลาก Item
ค้นหา
จัดการ State
ส่ง Callback กลับเกม

และสามารถรับ Message จาก FiveM Script ผ่าน Browser message Event ได้.

⑦ NUI ใช้ทำ HUD ได้ไหม

ได้

เช่น

Health
Armor
Hunger
Thirst
Money
Job
Voice
Speedometer

Fullscreen NUI ถูกวาง Overlay เหนือ Game View จึงเหมาะกับ HUD และ Interface ที่แสดงบนหน้าจอ.

⑧ NUI ใช้ทำ Inventory ได้ไหม

ได้

Inventory สามารถมี

Item Slots
Images
Drag & Drop
Amount
Weight
Search
Context Menu

และใช้ NUI Callback ส่ง Action กลับเข้าสู่ Game Script เมื่อผู้เล่นกดหรือใช้งาน Item.

⑨ NUI ใช้ทำ Phone ได้ไหม

ได้

Phone Resource สามารถสร้าง UI คล้าย Mobile Application ด้วย HTML/CSS/JavaScript แล้วเชื่อมข้อมูลกับ Client/Server Scripts

ตัว NUI เป็น Presentation Layer ส่วนข้อมูลหรือ Gameplay Authority ควรถูกควบคุมจาก Script/Server ตาม Architecture ของ Resource

⑩ NUI ต่างจาก HUD อย่างไร

จำง่าย ๆ

NUI
= เทคโนโลยี UI

HUD
= หนึ่งในสิ่งที่สร้างด้วย NUI

ตัวอย่าง

NUI
├── HUD
├── Inventory
├── Phone
├── Garage
└── Banking

NUI จึงกว้างกว่า HUD.

⑪ NUI ต่างจาก Loading Screen อย่างไร

Loading Screen เป็น NUI Frame ชนิดพิเศษที่ FiveM เรียกว่า

loadingScreen

และกำหนดด้วย loadscreen ใน Resource Manifest แทน ui_page.

ดังนั้น

Gameplay UI
→ ui_page

Loading Screen
→ loadscreen

⑫ NUI ต่างจาก DUI อย่างไร

Fullscreen NUI

UI Overlay บนหน้าจอ

ส่วน DUI — Direct-rendered UI

NUI ที่ Render ไปยัง Runtime Texture

Cfx.re ระบุว่า DUI สามารถนำไปใช้กับ Cinema Screen, Render Target หรือ UI ใน World Space ได้.

⑬ ตัวอย่าง NUI กับ DUI

Inventory Menu
→ NUI

HUD
→ NUI

Phone Fullscreen UI
→ NUI

TV Screen ในโลกเกม
→ DUI

Cinema Screen
→ DUI

DUI มี APIs เช่น CREATE_DUI, GET_DUI_HANDLE, SEND_DUI_MESSAGE และ DESTROY_DUI.

⑭ NUI ต่างจาก Scaleform อย่างไร

Scaleform เป็น GUI Technology ดั้งเดิมที่ GTA V ใช้ ซึ่ง Cfx.re ระบุว่าอิง Flash/ActionScript 2

ส่วน NUI ใช้ Web Technologies อย่าง HTML/CSS/JavaScript.

สำหรับ Custom UI สมัยใหม่ NUI มักเข้าใจและพัฒนาได้สะดวกสำหรับคนที่มีพื้นฐาน Web Development

⑮ Resource NUI ต้องมี fxmanifest.lua หรือไม่

ต้องมี Resource Manifest

Cfx.re ระบุว่า FiveM Resource ทุกตัวต้องมี fxmanifest.lua เพื่อกำหนด Files/Scripts ที่ Resource ใช้งาน.

ตัวอย่าง

my_nui/
├── fxmanifest.lua
├── client.lua
└── html/
├── index.html
├── style.css
└── app.js

⑯ ui_page คืออะไร

ui_page ใช้กำหนดหน้า NUI ของ Resource

ตัวอย่าง

ui_page 'html/index.html'

Cfx.re ระบุว่า ui_page สามารถชี้ไปยัง Local File หรือ URL และถ้าใช้ Local File ตัว File และ Dependencies ต้องถูกประกาศใน files.

⑰ ตัวอย่าง fxmanifest.lua สำหรับ NUI

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 และ files ตาม Resource Manifest ของ FiveM.

⑱ ทำไมต้องใส่ files

ถ้า

index.html

ต้องใช้

style.css
app.js
images
fonts

Files เหล่านี้ต้องถูก Resource จัดให้ Client ใช้งานตาม Manifest

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

⑲ NUI Resource ขั้นต่ำต้องมีอะไร

อย่างง่าย

fxmanifest.lua
client.lua
html/index.html
html/style.css
html/app.js

ไม่จำเป็นต้องใช้ React หรือ Framework ขนาดใหญ่หาก Interface ไม่ซับซ้อน

⑳ Flow การทำงานของ NUI

โครงสร้างที่ควรจำคือ

GAME DATA
↓
CLIENT SCRIPT
↓
SendNUIMessage
↓
NUI JavaScript
↓
DOM
↓
PLAYER

เมื่อผู้เล่นกด UI

PLAYER
↓
NUI JavaScript
↓
NUI Callback
↓
CLIENT SCRIPT
↓
SERVER ถ้าจำเป็น

Fullscreen NUI รองรับการส่ง Message จาก Game Script ไปยัง Browser UI และ NUI Callback ใช้ส่งข้อมูลกลับเข้าสู่ Game Script.

㉑ SendNUIMessage คืออะไร

Lua มี Function

SendNUIMessage({
action = 'open'
})

สำหรับส่ง Table Data เข้า NUI

Cfx.re ระบุว่า Lua Wrapper จะ Encode Data เป็น JSON ก่อนส่งเข้าสู่ NUI Page ของ Resource.

㉒ ตัวอย่างเปิด NUI

Client Lua

RegisterCommand('openmenu', function()

SendNUIMessage({
action = 'open'
})

end)

JavaScript

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

if (event.data.action === 'open') {
document.body.classList.add('open');
}

}
);

Browser-side message Event เป็น Pattern ที่ Cfx.re ใช้ใน Fullscreen NUI Documentation.

㉓ ส่งข้อมูลหลายค่าได้ไหม

ได้

ตัวอย่าง

SendNUIMessage({
action = 'playerData',
health = 100,
armor = 50,
job = 'police'
})

Lua Wrapper สามารถรับ Table แล้ว Encode เพื่อส่งเป็น Message ให้ NUI.

㉔ JavaScript รับข้อมูลอย่างไร

ตัวอย่าง

window.addEventListener(
'message',
(event) => {

const data = event.data;

if (data.action === 'playerData') {

console.log(data.health);
console.log(data.armor);
console.log(data.job);

}

}
);

นี่คือทิศทาง

FiveM
→ NUI

ผ่าน NUI Message.

㉕ NUI ส่งข้อมูลกลับ FiveM ได้หรือไม่

ได้

ใช้ NUI Callback

Cfx.re ระบุว่า NUI Callback เป็นวิธีส่งข้อมูลระหว่าง User Interface กับ Game และข้อมูลที่ส่งหรือรับต้องสามารถ Encode เป็น JSON ได้.

㉖ NUI Callback ใช้กับอะไร

ตัวอย่าง

ซื้อ Item
ใช้ Item
Save Settings
ปิด Menu
เลือก Character
ฝากเงิน
ถอนเงิน
เลือกรถ

แต่ Action สำคัญต้องผ่าน Validation ที่เหมาะสมก่อนเปลี่ยน Gameplay State

㉗ ตัวอย่าง NUI Callback ฝั่ง Lua

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

SetNuiFocus(
false,
false
)

cb({
ok = true
})

end
)

NUI Callback Documentation ระบุว่า Callback ควร Return Data ผ่าน cb.

㉘ ทำไมต้องตอบ cb

Cfx.re ระบุว่า หาก NUI Callback ไม่ Return ข้อมูลผ่าน cb Request สามารถ Timeout และ Error จะย้อนกลับไปยัง fetch ที่เรียกจาก UI.

ดังนั้นควรตอบอย่างน้อย

cb({
ok = true
})

㉙ ฝั่ง JavaScript เรียก Callback อย่างไร

แนวคิดคือ UI ส่ง Request กลับไปยัง NUI Callback Endpoint ของ Resource

ข้อมูลต้องเป็น JSON-compatible ตามข้อกำหนดของ NUI Callback.

โครงสร้างโดยรวมคือ

Button Click
↓
JavaScript Request
↓
NUI Callback
↓
Lua
↓
cb(...)
↓
JavaScript ได้ Response

㉚ NUI Focus คืออะไร

Fullscreen NUI อาจมีหรือไม่มี Input Focus

FiveM มี

SET_NUI_FOCUS

สำหรับกำหนด Keyboard Focus และ Mouse Cursor Focus ของ NUI Resource.

㉛ เปิด NUI Focus อย่างไร

ตัวอย่าง

SetNuiFocus(
true,
true
)

แนวคิดคือ

hasFocus = true
hasCursor = true

ทำให้ UI สามารถรับ Keyboard/Mouse ตาม Focus State ที่กำหนด.

㉜ ปิด NUI Focus อย่างไร

SetNuiFocus(
false,
false
)

เมื่อปิด Menu ควรคืน Input ให้ Gameplay

นี่ช่วยป้องกันปัญหา

เมาส์ค้าง
เดินไม่ได้
กดเกมไม่ได้

㉝ ตรวจว่า NUI มี Focus อยู่ไหม

FiveM มี

IS_NUI_FOCUSED

ซึ่งคืน Current NUI Focus State ที่เคยถูกตั้งผ่าน SET_NUI_FOCUS.

มีประโยชน์มากเวลา Debug Mouse ค้าง

㉞ HUD ต้องใช้ Focus ไหม

ถ้า HUD มีหน้าที่เพียงแสดง

Health
Armor
Money
Speed

ไม่จำเป็นต้องรับ Mouse/Keyboard Focus

ควรใช้ Focus เฉพาะ UI ที่ต้อง Interaction

㉟ Inventory ต้องใช้ Focus ไหม

โดยทั่วไป Inventory ที่ผู้เล่นต้อง

คลิก
ลาก
กด Button

ต้องมี Input Flow ที่เหมาะสม ซึ่งมักเกี่ยวข้องกับ NUI Focus

เมื่อปิด Inventory ต้องคืน Focus ให้ Game

㊱ NUI หลาย Resource แย่ง Focus กันได้ไหม

Cfx.re ระบุว่า NUI มี Focus Stack แบบจำกัด Resource ที่ถูก Focus ล่าสุดจะอยู่ด้านบน และ Fullscreen NUI Resources ทำงานเป็น Fullscreen iframes โดยไม่มี Click-through ระหว่าง Resources.

ดังนั้น Resource เช่น

Phone
Inventory
HUD Settings
Bank

ควรมี Lifecycle เปิด–ปิดชัดเจน

㊲ ทำไมเปิด Phone แล้ว Inventory คลิกไม่ได้

หนึ่งในสิ่งที่ควรตรวจคือ NUI Focus Stack

ถ้า Phone ได้ Focus หลัง Inventory

Phone อาจเป็น Resource ที่อยู่บน Focus Stack ล่าสุดตาม Behavior ที่ Cfx.re อธิบาย.

㊳ NUI Focus กับ Z-index เหมือนกันไหม

ไม่ควรถือว่าเป็นเรื่องเดียวกัน

CSS z-index จัดลำดับ Elements ภายในหน้า Web เดียว

ส่วน NUI Focus Stack เกี่ยวกับ Resource NUI และ Input/Ordering ระหว่าง Resources ตามกลไก FiveM.

㊴ NUI เปิดแต่เมาส์ไม่ขึ้น

ตรวจ

SetNuiFocus(true, true)

และตรวจว่า Resource อื่นไม่ได้เปลี่ยน Focus หลังจากนั้น.

㊵ NUI ปิดแล้วเมาส์ยังค้าง

ตรวจ Close Flow

ต้องมี

SetNuiFocus(
false,
false
)

หาก Resource ถูก Restart/Stop ขณะ Menu เปิด ก็ควรมี Cleanup ที่เหมาะสมด้วย

㊶ NUI เปิดไม่ขึ้นต้องตรวจอะไร

ตรวจตาม Layer

Resource
↓
fxmanifest.lua
↓
ui_page
↓
files
↓
HTML
↓
CSS
↓
JavaScript
↓
SendNUIMessage

ui_page และ Dependencies ของ Local UI ต้องถูกประกาศตาม Resource Manifest.

㊷ วิธี Test NUI ที่ง่ายที่สุด

ทำ HTML

<h1>NUI TEST</h1>

ถ้า UI Test แสดงได้

แสดงว่า

Resource
ui_page
HTML

ทำงานแล้ว

จากนั้นค่อยเพิ่ม JavaScript และ Data Integration

㊸ HTML ขึ้นแต่ข้อมูลไม่มา

ตอนนี้ให้ตรวจ

SendNUIMessage
Message Action
JavaScript Listener

Cfx.re รองรับ Message Flow จาก Script ไป Browser ผ่าน SEND_NUI_MESSAGE/SendNUIMessage.

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

ถ้า

console.log(event.data);

เห็นข้อมูลแล้ว

ปัญหาน่าจะอยู่

JavaScript Logic
DOM Selector
CSS
State

ไม่ใช่ FiveM Message Layer

㊺ Action Name ต้องตรงกัน

Client

SendNUIMessage({
action = 'openInventory'
})

JavaScript

if (
event.data.action
=== 'openInventory'
) {
// ...
}

ถ้าเขียน

openinventory

อีกฝั่งหนึ่ง Logic ก็จะไม่ตรงกัน

㊻ NUI DevTools คืออะไร

FiveM เปิด Chromium Developer Tools สำหรับ NUI และสามารถเรียกจาก F8 ด้วย

nui_devtools

ตาม Client Console Documentation.

เอกสาร Fullscreen NUI ยังระบุว่า CEF Remote Debugging Tools สามารถใช้ตรวจ NUI ขณะเกมทำงานได้.

㊼ NUI DevTools ดูอะไรได้

เช่น

Console
Elements
DOM
CSS
JavaScript Errors
Network

นี่คือเครื่องมือสำคัญที่สุดเมื่อ

HTML ขึ้น
แต่ UI ทำงานผิด

㊽ F8 ต่างจาก NUI DevTools อย่างไร

จำง่าย ๆ

F8
→ FiveM Client / Script Errors

NUI DevTools
→ HTML / CSS / JavaScript

ทั้งสองควรใช้ร่วมกันในการ Debug Resource ที่มี NUI.

㊾ NUI ทำ FPS ตกได้ไหม

มีโอกาสจาก Architecture และ Rendering Work

เช่น

ส่ง Message ถี่เกิน
JavaScript ทำงานมาก
DOM Update จำนวนมาก
Animation/Effects จำนวนมาก

ขณะเดียวกัน Client Script ของ Resource ก็อาจเป็นต้นเหตุได้

FiveM มี resmon สำหรับดู CPU/Memory Usage ของแต่ละ Resource.

㊿ ใช้ resmon ตรวจ NUI ได้อย่างไร

เปิด

resmon true

Resource Monitor จะแสดง CPU และ Memory Usage ของ Resources และ Cfx.re ระบุว่าเหมาะสำหรับตรวจ Performance Problems ระหว่าง Gameplay.

ถ้า NUI Resource ใช้ Client CPU สูง ควรตรวจ Client Loop เพิ่ม

51. อย่าส่ง NUI Message ทุกอย่างทุก Frame

ตัวอย่างที่ควรระวัง

while true do
Wait(0)

SendNUIMessage({
money = money,
job = job,
name = name,
health = health
})
end

แม้

money
job
name

ไม่ได้เปลี่ยน

ควรออกแบบ Data Updates ตามความถี่ของข้อมูล และใช้ Events/Change Detection เมื่อเหมาะสม

52. ส่งเฉพาะค่าที่เปลี่ยน

ตัวอย่าง

local lastMoney = nil

local function updateMoney(money)

if money == lastMoney then
return
end

lastMoney = money

SendNUIMessage({
action = 'money',
value = money
})

end

SendNUIMessage เป็น Transport จาก Script ไป NUI ดังนั้นการไม่ส่งค่าซ้ำที่ไม่มีผลต่อ UI เป็น Optimization เชิง Architecture ที่ดี.

53. JavaScript ก็ไม่ควร Render ค่าเดิมซ้ำ

ตัวอย่าง

if (lastMoney !== data.value) {

lastMoney = data.value;

moneyElement.textContent =
data.value;
}

ทำให้ Update เฉพาะเมื่อ Visual State เปลี่ยน

54. อย่า Render HTML ทั้งหน้าใหม่ทุก Message

ถ้าความเร็วเปลี่ยนเพียงหนึ่งค่า

ไม่จำเป็นต้อง Rebuild

HUD ทั้งหน้า

ใหม่

ควร Update เฉพาะ Element ที่เปลี่ยน

55. React ใช้กับ NUI ได้ไหม

ได้

Cfx.re ระบุว่า NUI รองรับ Web Frameworks อย่าง React และ Angular.

แต่ React ไม่ได้ทำให้ Resource เร็วหรือช้าโดยอัตโนมัติ

Performance ยังขึ้นกับ State Architecture และ Render Frequency

56. Vanilla JavaScript ใช้ได้ไหม

ได้

NUI ไม่บังคับให้ใช้ Framework

Resource เล็ก เช่น

Speedometer
Simple HUD
Popup
Confirmation Menu

สามารถใช้ HTML/CSS/JavaScript ปกติได้

57. NUI Callback ปลอดภัยหรือไม่

NUI Callback เป็นช่องทางรับข้อมูลจาก UI กลับเข้าสู่ Game Script แต่ข้อมูลจาก Client/UI ไม่ควรถูกถือว่าเชื่อถือได้สำหรับการทำ Action สำคัญโดยอัตโนมัติ

Cfx.re Security Guide เตือนว่าฝั่ง Client สามารถ Trigger Events ได้ใน Context ต่าง ๆ และ Server ควรตรวจข้อมูล/เงื่อนไขที่สำคัญเอง.

58. อย่าให้ NUI เป็นคนอนุมัติเงิน

ตัวอย่างที่ไม่ควรออกแบบ

NUI ส่ง
money = 1000000
↓
Server เชื่อทันที
↓
เพิ่มเงิน

UI ควรส่งเพียง Intent เช่น

withdraw 1000

แล้ว Server ตรวจ

ยอดเงินจริง
Permission
Transaction State
ข้อจำกัด

ก่อนดำเนินการ

แนวคิดนี้สอดคล้องกับ Cfx.re Security Guidance ที่ให้ Validate Logic สำคัญฝั่ง Server.

59. Inventory Item ก็เช่นกัน

ไม่ควรให้ NUI บอกว่า

ฉันมี Item 100 ชิ้น

แล้ว Server เชื่อ

Server ควรเป็น Source of Truth สำหรับข้อมูล Gameplay สำคัญ เช่น Inventory, Money และ Permission

60. NUI Callback Data ต้องเป็นอะไร

Cfx.re ระบุว่าข้อมูลที่ส่งและรับผ่าน NUI Callback ต้องสามารถ JSON Encode ได้.

ดังนั้น Structure ควรเป็นข้อมูลพื้นฐาน เช่น

string
number
boolean
array
object/table ที่ Encode ได้

61. NUI Resource ควรแยก Data กับ Presentation

Architecture ที่ดูแลง่ายคือ

SERVER
↓
CLIENT DATA ADAPTER
↓
NUI STATE
↓
RENDER

ไม่ควรให้ HTML/JavaScript เป็นเจ้าของ Gameplay Authority

62. ตัวอย่าง Architecture Inventory

Database / Server Inventory
↓
Server
↓
Client
↓
SendNUIMessage
↓
Inventory UI

เมื่อผู้เล่นกด Use Item

Inventory UI
↓
NUI Callback
↓
Client
↓
Server Validation
↓
Action

ทำให้ Presentation กับ Gameplay Logic แยกออกจากกัน

63. NUI รองรับหลาย Resolution หรือไม่

เพราะเป็น Web UI จึงสามารถออกแบบ Responsive ด้วย CSS ได้

ควรทดสอบ

1920×1080
2560×1440
4K
21:9
Ultrawide

และหลีกเลี่ยง Hard-code ตำแหน่งเฉพาะ Resolution เดียว

64. ตัวอย่าง Responsive Layout

.menu {
width: min(
90vw,
800px
);

max-height: 85vh;
}

ช่วยให้ UI ปรับตาม Viewport ได้ง่ายกว่าใช้ขนาด Pixel ตายตัวทั้งหมด

65. NUI ใช้ภาพและ Font ได้ไหม

ได้ในฐานะ Web Assets

แต่ถ้าเป็น Local Files ของ Resource ต้องประกาศให้ Resource จัดส่ง Files ที่ Dependencies ต้องใช้ตาม files ใน Manifest.

66. External URL เป็น ui_page ได้ไหม

ได้

Cfx.re Resource Manifest ระบุว่า ui_page รองรับทั้ง Local File และ Absolute URL.

อย่างไรก็ตาม External UI เพิ่ม Dependency ต่อ Host/Network ภายนอก จึงควรเลือกตาม Infrastructure และ Availability ที่ต้องการ

67. NUI กับ DUI ใช้ Message ต่างกันหรือไม่

Fullscreen NUI ใช้

SEND_NUI_MESSAGE

ส่วน DUI มี

SEND_DUI_MESSAGE

สำหรับส่ง JSON Message ไปยัง DUI Root Page.

ดังนั้นควรเลือก API ตาม UI Type

68. DUI เหมาะกับอะไร

Cfx.re ยกตัวอย่าง

Cinema Screens
2D Sprite Rendering
Game Render Targets
World-space UI

สำหรับ DUI.

ถ้าต้องการ Inventory เต็มหน้าจอ ไม่จำเป็นต้องใช้ DUI

69. Loading Screen ใช้ SendNUIMessage เหมือน HUD ไหม

Loading Screen เป็น NUI Frame พิเศษ และ FiveM มี SEND_LOADING_SCREEN_MESSAGE สำหรับส่ง Message ไปยัง Loading Screen โดยเฉพาะ.

ดังนั้น

Gameplay NUI
→ SendNUIMessage

Loading Screen
→ SendLoadingScreenMessage

ตาม Use Case

70. วิธี Debug NUI ไม่ขึ้นแบบเร็วที่สุด

ขั้นที่ 1 — Resource

ตรวจว่า Resource Started

ขั้นที่ 2 — Manifest

ตรวจ

fxmanifest.lua
ui_page
files

ui_page และ Dependencies ต้องประกาศให้ถูกต้อง.

ขั้นที่ 3 — HTML Test

ใส่

<h1>NUI TEST</h1>

ขั้นที่ 4 — Send Test Message

SendNUIMessage({
action = 'test'
})

SendNUIMessage ใช้ส่งข้อมูลเข้า NUI Page ของ Resource.

ขั้นที่ 5 — JavaScript

window.addEventListener(
'message',
event => {
console.log(event.data);
}
);

Pattern นี้อยู่ใน Fullscreen NUI Documentation.

ขั้นที่ 6 — DevTools

เปิด

nui_devtools

จาก F8.

ขั้นที่ 7 — Focus

ถ้า UI ขึ้นแต่คลิกไม่ได้ ตรวจ SET_NUI_FOCUS.

ขั้นที่ 8 — Callback

ถ้าปุ่มทำงานแต่ Request ค้าง ตรวจ NUI Callback และ cb.

ขั้นที่ 9 — Performance

ใช้

resmon true

ตรวจ Resource CPU/Memory.

ขั้นที่ 10 — Security

Action สำคัญให้ Server Validate ก่อนเปลี่ยน State.

71. ตารางสรุปปัญหา FiveM NUI

อาการจุดที่ควรตรวจ
NUI ไม่ขึ้นเลยResource / ui_page
HTML ไม่โหลดfiles / Path
UI ขึ้นแต่ไม่มีข้อมูลSendNUIMessage
Message เข้าแต่ UI ไม่เปลี่ยนJavaScript / DOM
UI เปิดแต่คลิกไม่ได้NUI Focus
Mouse ค้างหลังปิดFocus Cleanup
Callback กดแล้วค้างไม่ตอบ cb
Inventory เปิดทับ PhoneFocus/Lifecycle
JavaScript ErrorNUI DevTools
Resource CPU สูงresmon
UI หน่วงMessage/DOM/Rendering
DUI ไม่ขึ้นDUI Lifecycle
Loading Screen Message ไม่เข้าใช้ API ผิด Frame
Action เงิน/Item ไม่ปลอดภัยServer Validation

72. Checklist NUI ก่อนขึ้น Production

☐ fxmanifest.lua ถูก
☐ ui_page ถูก
☐ files ครบ
☐ HTML โหลด
☐ CSS โหลด
☐ JavaScript โหลด
☐ SendNUIMessage ทำงาน
☐ Message Handler ทำงาน
☐ Focus เปิดถูก
☐ Focus ปิดถูก
☐ Callback ทำงาน
☐ Callback ตอบ cb
☐ Resource Restart ได้
☐ ไม่มี Duplicate Event Handlers
☐ ไม่มี Message ที่ส่งซ้ำเกินจำเป็น
☐ Responsive
☐ 1080p ผ่าน
☐ 1440p ผ่าน
☐ 4K ผ่าน
☐ Ultrawide ผ่าน
☐ Server Validate Action สำคัญ
☐ resmon ไม่สูงผิดปกติ

73. ตัวอย่าง NUI Resource แบบพื้นฐาน

โครงสร้าง

simple_nui/
├── fxmanifest.lua
├── client.lua
└── html/
├── index.html
├── style.css
└── app.js

fxmanifest.lua

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 และ files ทำหน้าที่ตาม Resource Manifest ของ FiveM.

74. ตัวอย่าง client.lua

local menuOpen = false

RegisterCommand(
'testmenu',
function()

menuOpen =
not menuOpen

SetNuiFocus(
menuOpen,
menuOpen
)

SendNUIMessage({
action =
menuOpen
and 'open'
or 'close'
})

end
)

ตัวอย่างนี้ใช้ SET_NUI_FOCUS และ SendNUIMessage ซึ่งเป็น APIs หลักของ Fullscreen NUI.

75. ตัวอย่าง index.html

<!DOCTYPE html>

<html>
<head>

<meta charset="UTF-8">

<link
rel="stylesheet"
href="style.css">

</head>

<body>

<div
id="menu"
class="hidden">

<h1>FiveM NUI</h1>

<button id="close">
Close
</button>

</div>

<script src="app.js"></script>

</body>
</html>

76. ตัวอย่าง app.js รับ Message

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

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

const data =
event.data;

if (
data.action === 'open'
) {
menu.classList.remove(
'hidden'
);
}

if (
data.action === 'close'
) {
menu.classList.add(
'hidden'
);
}

}
);

FiveM ใช้ Browser message Event สำหรับรับ Messages จาก Game Script ตาม Fullscreen NUI Documentation.

77. NUI ที่ดีควรแบ่ง Layer

แนะนำ Architecture

SERVER
↓
CLIENT
↓
UI ADAPTER
↓
NUI MESSAGE
↓
UI STATE
↓
DOM / COMPONENTS

และย้อนกลับ

UI ACTION
↓
NUI CALLBACK
↓
CLIENT
↓
SERVER VALIDATION
↓
RESULT

แนวทางนี้ช่วยให้ UI ไม่กลายเป็น Source of Truth สำหรับ Gameplay ที่ต้องรักษาความปลอดภัย.

78. สิ่งที่ไม่ควรทำกับ FiveM NUI

หลีกเลี่ยง

SendNUIMessage ทุกข้อมูลทุก Frame
Register Event ซ้ำ
สร้าง Timer ซ้ำ
Update DOM ทั้งหน้าทุกครั้ง
เปิด Focus ค้างตลอด
ไม่คืน Focus ตอนปิด UI
ไม่ตอบ NUI Callback
เชื่อข้อมูล NUI เพื่อเพิ่มเงินหรือ Item
Hard-code เฉพาะ 1920×1080
แก้ CSS โดยไม่เปิด NUI DevTools

โดยเฉพาะ Callback ที่ไม่ตอบ cb สามารถ Timeout ได้ และ Gameplay Action ที่มาจาก Client ควรผ่าน Server-side Validation ตาม Security Guidance ของ Cfx.re.

สูตรจำง่ายสำหรับ FiveM NUI

GAME
↓
MESSAGE
↓
NUI
↓
USER
↓
CALLBACK
↓
GAME

หรือแบบเต็ม

SERVER
↓
CLIENT
↓
SendNUIMessage
↓
HTML / CSS / JS
↓
PLAYER
↓
NUI Callback
↓
CLIENT
↓
SERVER

สรุป FiveM NUI คืออะไร

FiveM NUI คือระบบ HTML-based User Interface ของ CitizenFX Framework ที่ช่วยให้ Developer สร้าง Interface ภายใน FiveM ด้วย HTML, CSS และ JavaScript และรองรับ Framework อย่าง React/Angular รวมถึง WebGL ตามความต้องการ.

Fullscreen NUI ถูกแสดงเป็น UI Page Overlay เหนือ Game View และกำหนดผ่าน

ui_page 'html/index.html'

ใน fxmanifest.lua โดย Local UI File และ Dependencies ต้องประกาศใน files.

สำหรับการส่งข้อมูลจาก FiveM Script ไปยังหน้า UI ใช้

SendNUIMessage

แล้ว JavaScript รับข้อมูลผ่าน Browser message Event.

สำหรับการส่งข้อมูลกลับจาก UI เข้า Game ใช้ NUI Callback และต้องตอบ cb เพื่อไม่ให้ Request Timeout.

ถ้า UI ต้องรับ Mouse/Keyboard ใช้

SET_NUI_FOCUS

และสามารถตรวจ Current Focus ด้วย IS_NUI_FOCUSED.

ถ้าต้องการ Render Web UI ลงบน Texture หรือ Object ภายในโลกเกม ให้ดู DUI — Direct-rendered UI ซึ่ง FiveM รองรับแยกจาก Fullscreen NUI.

ถ้า NUI ไม่ขึ้น ให้ตรวจ fxmanifest.lua → ui_page → files → HTML

ถ้า UI ขึ้นแต่ข้อมูลไม่มา ให้ตรวจ SendNUIMessage

ถ้า ข้อมูลเข้าแต่หน้าจอไม่เปลี่ยน ให้ตรวจ JavaScript/DOM ผ่าน nui_devtools.

ถ้า เมาส์ค้างหลังปิด Menu ให้ตรวจ NUI Focus

ถ้า Callback ค้าง ให้ตรวจว่ามีการตอบ cb

และหาก NUI เกี่ยวข้องกับ เงิน, Inventory, Permission หรือ Action สำคัญ อย่าเชื่อค่าจาก Client/UI โดยตรง แต่ให้ Server ตรวจ Gameplay State และเงื่อนไขที่สำคัญก่อน เพราะ Cfx.re เตือนว่า Client สามารถ Trigger Events ได้และแนะนำให้รักษา Server-side Validation.

แนวทางของ comsiam คือแยก FiveM NUI ออกเป็น Data → Message → UI State → Rendering → Callback → Server Validation ให้ชัดตั้งแต่เริ่มพัฒนา เมื่อเกิดปัญหาจะรู้ทันทีว่าต้องตรวจ Data, NUI Message, JavaScript, Focus, Callback หรือ Server Logic แทนการแก้ทุกส่วนพร้อมกัน

Comments

Popular posts from this blog

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

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

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