FiveM HUD กระตุกหรือทำให้ FPS ตก แก้อย่างไร
ปัญหา FiveM HUD กระตุก, HUD หน่วง, Speedometer กระตุก, เปิด HUD แล้ว FPS ลด หรือ Custom HUD กินทรัพยากรเครื่องสูง ไม่ควรแก้ด้วยการลดกราฟิก GTA เพียงอย่างเดียว เพราะต้นเหตุอาจอยู่ที่ Client Script, Loop ที่ทำงานถี่เกินไป, NUI Message, JavaScript, DOM, CSS Animation หรือ Resource อื่นที่ทำงานร่วมกับ HUD
FiveM มีเครื่องมือสำหรับวิเคราะห์ปัญหา Performance โดยตรง ได้แก่ Resource Monitor (resmon) ซึ่งแสดง CPU และ Memory ของแต่ละ Resource และ Profiler ซึ่งสามารถใช้ตรวจหาว่า Thread หรือ Code ส่วนใดกำลังใช้เวลาในการประมวลผลสูง.
บทความนี้จาก comsiam จะเน้นการหาต้นเหตุจริงก่อน Optimize เพื่อไม่ให้ต้องเปลี่ยน HUD ใหม่ทั้งชุดโดยไม่รู้ว่าปัญหาเกิดจากอะไร
① FiveM HUD กระตุกมีอาการอย่างไร
อาการที่พบบ่อย เช่น
HUD ขยับไม่ลื่น
Speedometer กระโดด
Health Bar หน่วง
Voice Icon กระตุก
เข้า Vehicle แล้ว FPS ลด
เปิด HUD แล้ว FPS จาก 120 เหลือ 70
HUD Update ช้า
NUI ค้างเป็นช่วง ๆ
FPS ตกเฉพาะเมื่อ HUD เปิด
ปิด HUD แล้ว FPS กลับปกติ
อาการเหล่านี้ไม่ได้หมายความว่า HTML หรือ CSS เป็นสาเหตุเสมอไป
② แยกก่อนว่า FPS ตกจริงหรือ HUD แค่ Update ช้า
สองอาการนี้ต่างกัน
FPS ตกจริง
ตัวเกมทั้งเกมกระตุก
กล้องไม่ลื่น
รถกระตุก
Animation กระตุก
FPS ลด
HUD Update ช้า
ตัวเกมยังลื่น แต่
Speedometer กระโดด
Health Bar อัปเดตช้า
Fuel เปลี่ยนเป็นช่วง ๆ
กรณีหลังอาจเกิดจาก Update Interval ที่ช้าเกิน ไม่จำเป็นต้องเป็น Performance Problem
③ เปิดตัวเลข FPS ก่อนแก้
FiveM มี
cl_drawfps true
สำหรับแสดง FPS และมี
cl_drawperf true
สำหรับแสดงข้อมูล Performance เพิ่มเติม เช่น FPS, Ping, Packet Loss, CPU Usage และ GPU Usage.
ก่อน Optimize ควรจดค่าก่อนและหลังเปิด HUD
④ วิธีทดสอบ HUD ว่าทำ FPS ตกจริงหรือไม่
ทดสอบแบบ A/B
HUD ON
→ จด FPS
HUD OFF
→ จด FPS
ทำใน
จุดเดียวกัน
รถคันเดียวกัน
จำนวนผู้เล่นใกล้เคียงกัน
สภาพแวดล้อมเดียวกัน
ถ้า HUD ON ลดลงชัดเจนหลายครั้งติดต่อกัน จึงค่อยวิเคราะห์ Resource HUD
⑤ อย่าดู FPS ครั้งเดียว
FPS เปลี่ยนได้จาก
จำนวนรถ
จำนวน Ped
Map
MLO
ผู้เล่นใกล้เคียง
Weather
GPU Load
ดังนั้นควรทดสอบหลายรอบ
ไม่ควรสรุปจากการเข้า Server ครั้งเดียวว่า HUD ทำ FPS ตก
⑥ ใช้ resmon เป็นจุดเริ่มต้น
FiveM Resource Monitor สามารถเปิดด้วย
resmon true
และ Cfx.re ระบุว่าใช้ดูว่า Resource ใดใช้เวลาประมวลผลสูง รวมถึงแสดง CPU Usage ในหน่วยเวลาและ Memory ของแต่ละ Resource.
ถ้าสงสัย Resource ชื่อ
custom_hud
ให้ดูว่าค่าของ Resource นี้สูงผิดปกติหรือไม่
⑦ resmon ไม่ใช่ Windows Resource Monitor
คำว่า
resmon true
ในบริบทนี้หมายถึง Resource Monitor ของ FiveM
ใช้วิเคราะห์ Resources ที่กำลังทำงานใน Client
ไม่ใช่โปรแกรม Resource Monitor ของ Windows
⑧ resmon ขึ้น Access Denied ทำอย่างไร
Cfx.re ระบุว่า Developer Commands บางตัวอาจถูกปิดใน Production Mode และ resmon อาจแจ้ง Access Denied หาก Developer Mode ยังไม่เปิดใช้งาน.
ดังนั้นอย่าสรุปว่าคำสั่งถูกลบหรือ FiveM เสีย
⑨ Resource HUD ใช้ CPU สูงแปลว่าอะไร
หมายความว่าต้องตรวจ Client Script ของ HUD ก่อน
อาจมี
Loop ถี่เกิน
Native Calls มากเกิน
Framework Query ซ้ำ
Vehicle Calculation มากเกิน
String/Table Processing ซ้ำ
แต่ยังไม่ได้พิสูจน์ว่า NUI/HTML เป็นสาเหตุ
⑩ Resource HUD CPU ต่ำแต่ FPS ยังตกได้ไหม
ได้
เพราะ Custom HUD แบบ NUI ใช้ Web UI ด้วย
ดังนั้นอาจมีงานหนักฝั่ง
JavaScript
DOM
CSS
CEF Rendering
ขณะที่ Client Script ดูไม่ได้หนักมาก
FiveM NUI ใช้ HTML-based UI บน Chromium Embedded Framework.
⑪ NUI คืออะไรในปัญหา FPS
Custom HUD จำนวนมากทำงานเป็น Fullscreen NUI Overlay
Cfx.re ระบุว่า Fullscreen NUI เป็น UI Page ที่ Overlay อยู่เหนือเกม และ Script สามารถส่ง Message เข้า NUI ด้วย SEND_NUI_MESSAGE หรือ SendNUIMessage ใน Lua.
ดังนั้น HUD Performance มีทั้ง Script Layer และ Browser/UI Layer
⑫ SendNUIMessage ทำอะไร
FiveM มี
SendNUIMessage({
action = 'update',
value = 100
})
เพื่อส่ง Table Data ไปยัง NUI.
การเรียก Function นี้ไม่ใช่ปัญหาโดยตัวมันเอง แต่ถ้าเรียกถี่เกินและส่งข้อมูลจำนวนมากโดยไม่จำเป็น UI จะต้องรับและประมวลผล Message เหล่านั้นต่อ
⑬ ปัญหายอดนิยมคือส่งข้อมูลทุก Frame
ตัวอย่าง
CreateThread(function()
while true do
Wait(0)
SendNUIMessage({
health = health,
armor = armor,
money = money,
job = job,
hunger = hunger,
thirst = thirst,
speed = speed,
fuel = fuel
})
end
end)
Wait(0) จะ Yield Thread จนถึง Game Tick ถัดไป ดังนั้น Loop รูปแบบนี้สามารถทำงานทุก Tick.
คำถามคือข้อมูลทุกตัวจำเป็นต้อง Update ทุก Tick จริงหรือไม่
⑭ Wait(0) ไม่ได้ผิดเสมอไป
Cfx.re ระบุว่า Logic ที่ จำเป็นต้องทำงานทุก Frame ควรใช้ Wait(0) แต่ก็แนะนำให้หลีกเลี่ยง Heavy Native Calls แบบ Per-tick หากไม่จำเป็น และสามารถ Cache ค่าที่เปลี่ยนไม่บ่อยได้.
ดังนั้น
Wait(0)
ไม่ใช่ Bug
สิ่งที่ต้องดูคือ มีอะไรอยู่ใน Loop
⑮ Speedometer อาจต้อง Update บ่อย
ข้อมูลเช่น
Speed
RPM
เปลี่ยนอย่างต่อเนื่องระหว่างขับรถ
จึงต้อง Update บ่อยกว่าข้อมูลอย่าง
Job
Money
Server ID
แต่ไม่จำเป็นว่าทุก Vehicle Variable ต้อง Query ทุก Game Tick
⑯ Money ไม่ควร Query ทุก Frame
เงินมักเปลี่ยนเมื่อเกิด Transaction
ดังนั้นควรเป็นแนวคิด
เงินเปลี่ยน
↓
Update HUD
แทน
ทุก Frame
↓
ถามว่าเงินเท่าไร
↓
ส่งค่าเดิมไป HUD
⑰ Job ก็ไม่ควร Query ทุก Frame
Job อาจเปลี่ยนเมื่อ
ผู้เล่น Login
เปลี่ยนอาชีพ
เปลี่ยน Grade
จึงสามารถใช้ Event-driven Update มากกว่า Polling ทุก Tick
⑱ Health ควร Update อย่างไร
Health ต้องตอบสนองค่อนข้างเร็ว แต่ไม่จำเป็นต้องรวมอยู่ใน Loop เดียวกับข้อมูลทุกอย่าง
สามารถมี
Health Loop
ที่ Update ตามช่วงเวลาที่เหมาะสม หรือส่งเฉพาะเมื่อค่าต่างจากครั้งก่อน
⑲ ใช้ Cache ค่าเดิม
ตัวอย่าง
local lastHealth = nil
CreateThread(function()
while true do
Wait(100)
local ped = PlayerPedId()
local health = GetEntityHealth(ped)
if health ~= lastHealth then
lastHealth = health
SendNUIMessage({
action = 'health',
value = health
})
end
end
end)
หลักการคือ
ค่าไม่เปลี่ยน
→ ไม่ส่ง
ค่าเปลี่ยน
→ ส่ง
ช่วยลดงานที่ไม่มีผลต่อสิ่งที่ผู้เล่นเห็น
⑳ Cache Native ที่เรียกบ่อยได้ไหม
Cfx.re ระบุในคำแนะนำของ Citizen.Wait ว่า Native บางตัวซึ่งค่าเปลี่ยนไม่บ่อยสามารถ Cache ใน Thread ที่ทำงานช้ากว่า เพื่อลด Native Calling Overhead.
อย่างไรก็ตามต้องเลือกเฉพาะค่าที่เหมาะกับการ Cache
อย่า Cache ค่าที่ต้องแม่นทุก Frame
㉑ แยก HUD เป็น Fast, Medium และ Event Data
Architecture ที่ดีสามารถแบ่งเป็น
Fast Data
→ Speed / RPM
Medium Data
→ Health / Armor / Hunger
Event Data
→ Money / Job / Voice Mode / Player ID
จากนั้นใช้ Update Strategy คนละแบบ
㉒ Vehicle HUD ควรทำงานเฉพาะตอนอยู่รถ
ถ้า Player เดินอยู่
GetVehiclePedIsIn
Speed
RPM
Gear
Fuel
Seatbelt
หลายส่วนไม่จำเป็นต้องคำนวณตลอด
ควรมี State
In Vehicle?
ก่อนเปิด Vehicle HUD Processing
㉓ Driver กับ Passenger ควรแยกไหม
ถ้า Speedometer ใช้เฉพาะ Driver
สามารถลดงานเพิ่มเติมด้วย
อยู่ในรถ?
↓
เป็น Driver?
↓
ค่อย Update Vehicle HUD
แต่ขึ้นอยู่กับ Design ว่าต้องการให้ Passenger เห็นข้อมูลหรือไม่
㉔ ลงรถแล้วควรลด Loop Frequency
ตัวอย่างแนวคิด
local sleep = 1000
if inVehicle then
sleep = 50
end
Wait(sleep)
Cfx.re เองยกตัวอย่างแนวทางปรับ Wait ตามสถานการณ์ เพื่อไม่ต้องตรวจสิ่งที่ไม่จำเป็นตลอดเวลา.
㉕ Dynamic Sleep คืออะไร
คือการเปลี่ยนเวลารอของ Loop ตาม State
ตัวอย่าง
ไม่ได้ใช้ HUD Element
→ Wait นาน
กำลังใช้งาน
→ Wait สั้น
ช่วยลด CPU Work เมื่อ Feature ไม่ถูกใช้งาน
㉖ ตัวอย่าง Vehicle HUD แบบ Dynamic Sleep
CreateThread(function()
while true do
local sleep = 1000
local ped = PlayerPedId()
if IsPedInAnyVehicle(ped, false) then
sleep = 50
local vehicle = GetVehiclePedIsIn(ped, false)
local speed = GetEntitySpeed(vehicle)
-- update HUD if needed
end
Wait(sleep)
end
end)
นี่เป็น Pattern เชิง Optimization ไม่ใช่ข้อกำหนดว่าต้องใช้ 50 หรือ 1000 ms ทุก Server
㉗ อย่า Copy Wait จาก HUD อื่นแบบสุ่ม
ค่า
Wait(0)
Wait(10)
Wait(50)
Wait(100)
Wait(500)
ไม่มีค่าที่ดีที่สุดสำหรับทุก Resource
ต้องดูว่า UI ต้องตอบสนองเร็วแค่ไหน และ Code ใน Loop หนักแค่ไหน
㉘ Speedometer กระโดดหลังเพิ่ม Wait สูง
ถ้าปรับ
Wait(1000)
ให้ Speedometer
ผู้เล่นจะเห็น Speed เปลี่ยนประมาณทีละวินาที
จึงดูไม่ลื่น
Optimization ไม่ควรแลก UX จนเสีย
㉙ Optimize ไม่ได้แปลว่าเพิ่ม Wait อย่างเดียว
ควรใช้หลายวิธีร่วมกัน
ลด Native Calls
Cache Data
Event-driven Updates
ส่งเฉพาะค่าที่เปลี่ยน
ลด DOM Updates
ลด CSS Effects
ไม่ใช่เพียงเปลี่ยนทุก Loop เป็น Wait(1000)
㉚ แยก Loop ใหญ่เป็นหลายระบบดีไหม
บางกรณีดี
เช่น
Player Status Thread
Vehicle Thread
Voice Thread
Framework Event Handler
ทำให้แต่ละส่วนมี Update Frequency ของตัวเอง
แต่การสร้าง Threads จำนวนมากโดยไม่มีโครงสร้างก็ไม่ได้แปลว่าจะเร็วกว่าเสมอ
㉛ ปัญหา NUI Message ใหญ่เกินไป
ถ้า HUD ส่งข้อมูล
Health
Armor
Money
Job
Speed
RPM
Fuel
Compass
Street
Voice
Radio
Hunger
Thirst
Stress
ทั้งหมดทุกครั้ง แม้เปลี่ยนเพียง Speed
NUI ต้องรับ Object เดิมซ้ำจำนวนมาก
ควรพิจารณา Update เฉพาะ State ที่เปลี่ยนหรือ Batch ตามประเภท
㉜ ส่ง Message ย่อยดีไหม
ตัวอย่าง
SendNUIMessage({
action = 'speed',
value = speed
})
เมื่อ Speed เปลี่ยน
ส่วน Job ส่งเมื่อ Job เปลี่ยน
ช่วยทำให้ Data Flow ชัด
แต่ถ้าส่ง Message ย่อยจำนวนมากพร้อมกันทุก Frame ก็อาจไม่ได้ช่วย
ต้องดูภาพรวม
㉝ Batch Message คืออะไร
อีกแนวทางคือรวมข้อมูลที่ Update พร้อมกัน
SendNUIMessage({
action = 'vehicle',
speed = speed,
rpm = rpm,
fuel = fuel
})
ลดจำนวน Message Calls แต่อาจยัง Update เฉพาะ Vehicle State
จุดสำคัญคือไม่ส่งข้อมูลที่ไม่เกี่ยวข้องทุกครั้ง
㉞ JavaScript รับ Message อย่างไร
Fullscreen NUI ของ FiveM ใช้ Browser-side message Event รับข้อมูลที่ส่งจาก Game Script.
ตัวอย่างแนวคิด
window.addEventListener('message', (event) => {
const data = event.data;
if (data.action === 'vehicle') {
// update vehicle HUD
}
});
ถ้า Handler ทำงานหนักทุก Message ก็สามารถกลายเป็นอีกจุดที่ต้อง Optimize
㉟ console.log ทุก Frame ควรลบไหม
ใน Development ใช้ Log ช่วย Debug ได้ดี
แต่ Code เช่น
console.log(event.data);
สำหรับ Message ที่เข้าทุก Frame ไม่ควรถูกปล่อยโดยไม่จำเป็นใน Production
เพราะเป็นงานเพิ่มเติมและทำให้ Console เต็มอย่างรวดเร็ว
㊱ DOM Update คืออะไร
ตัวอย่าง
element.innerText = value;
element.style.width = value + '%';
คือการแก้ข้อมูล/Style ของ Element ในหน้า UI
ถ้าทำซ้ำแม้ค่าจะไม่เปลี่ยนก็เป็นงานที่ไม่ก่อประโยชน์
㊲ JavaScript ควรตรวจค่าเดิมไหม
ได้
ตัวอย่าง
if (lastSpeed !== data.speed) {
lastSpeed = data.speed;
speedElement.textContent = data.speed;
}
แนวคิดเดียวกับ Cache ฝั่ง Lua
ค่าเดิม
→ ไม่ Render ใหม่
ค่าใหม่
→ Update
㊳ เปลี่ยน innerHTML ทั้ง HUD ทุก Tick ดีไหม
ไม่ควรเป็นวิธีแรก
ตัวอย่าง
hud.innerHTML = `...ทั้งหมด...`;
ทุก Message ทำให้ UI ต้องสร้าง/จัดการ Elements ใหม่มากกว่าการเปลี่ยน Text หรือ Width เพียง Element ที่เปลี่ยน
ควร Update เฉพาะจุดเท่าที่จำเป็น
㊴ React HUD ทำ FPS ตกกว่า Vanilla JS ไหม
ไม่ควรสรุปจากชื่อ Framework
FiveM NUI รองรับ Web Technologies และ Framework อย่าง React หรือ Angular ได้.
Performance ขึ้นกับ
Architecture
Render Frequency
State Updates
Components
Effects
มากกว่าชื่อ Framework อย่างเดียว
㊵ React re-render ทุก Tick ต้องระวัง
ถ้า State Root ใหญ่ถูก Update ทุก Message
อาจทำให้ Component Tree จำนวนมาก Re-render โดยไม่จำเป็น
ควรแยก State และ Components
เช่น
PlayerStatus
VehicleHUD
VoiceHUD
ไม่ให้ Speed Update บังคับทุกส่วนของ HUD Render ใหม่
㊶ CSS Animation ทำ HUD หนักได้ไหม
สามารถเพิ่ม Rendering Work ได้ โดยเฉพาะเมื่อมี Effects จำนวนมาก เช่น
Animation ตลอดเวลา
Blur หลาย Layer
Large Shadow
Glow
Transparency
Animated Gradient
แต่ต้องทดสอบจริง
อย่าลบ Effects ทั้งหมดก่อนวัด Performance
㊷ HUD ที่ไม่มี Animation ก็หนักได้
ถ้า Client Script มี Loop หนัก
แม้ UI จะเป็นแค่ Text ธรรมดาก็สามารถทำ FPS ลดได้
ดังนั้นหน้าตาเรียบไม่ได้หมายความว่า Resource Optimize แล้ว
㊸ HUD สวยไม่ได้หมายความว่าหนัก
ในทางกลับกัน HUD ที่มี Animation บางส่วนอาจทำงานได้ดี หาก
Data Flow ดี
DOM จำกัด
Loop Optimize
UI Render มีประสิทธิภาพ
จึงต้องวัดผลจริง
㊹ NUI DevTools ใช้ตรวจอะไร
FiveM Fullscreen NUI เปิด CEF Developer Tools ได้ และเอกสารระบุว่าสามารถใช้คำสั่ง
nui_devTools
จาก F8 ได้เมื่อ Developer Mode พร้อม.
ใช้ตรวจ
Console
DOM
CSS
JavaScript
Performance
ได้
㊺ ถ้า HUD FPS ตกเมื่อเปิด Settings Menu
ให้ตรวจ UI ที่เพิ่มขึ้นตอน Settings เปิด
เช่น
Color Picker
Preview
Animations
Sliders
Large Menus
เพราะ Gameplay HUD อาจปกติ แต่ Settings NUI เป็นส่วนที่หนัก
㊻ NUI Focus ทำให้ FPS ตกไหม
การ Focus ไม่ควรถูกสรุปว่าเป็นสาเหตุหลักโดยอัตโนมัติ
SET_NUI_FOCUS มีหน้าที่ควบคุม Keyboard และ Mouse Focus ของ NUI.
ถ้าเปิด Settings แล้ว FPS ลด ควรดูสิ่งที่ UI Render เพิ่ม ไม่ใช่โทษ Focus อย่างเดียว
㊼ หลาย NUI Resources พร้อมกันมีผลไหม
FiveM Fullscreen NUI Resources ทำงานเป็น Fullscreen iframes และมี Focus Stack.
ถ้า Server มี
HUD
Phone
Inventory
Radio
Clothing Menu
Scoreboard
พร้อมกันหลาย NUI Resource ควรตรวจว่า Resource ไหนทำงาน/Render อยู่ในช่วงที่ FPS ลด
㊽ ปิด HUD Resource ชั่วคราวเพื่อ A/B Test
บน Test Server
HUD ON
→ วัด
HUD OFF
→ วัด
จากนั้นถ้า HUD เป็นต้นเหตุจริง ค่อย Optimize ภายใน
วิธีนี้ดีกว่าการแก้ทุก Resource พร้อมกัน
㊾ ปิดเฉพาะ Vehicle HUD เพื่อหา Root Cause
ถ้า FPS ลดเฉพาะตอนขึ้นรถ
ทดสอบ
Player HUD ON
Vehicle HUD OFF
ถ้า FPS กลับมา
ให้เน้น
Speed
RPM
Fuel
Compass
Street
Vehicle Native Calls
ก่อนส่วน Health/Armor
㊿ Compass และ Street Name อาจเป็นจุดหนักได้ไหม
ได้หาก Resource Query/คำนวณข้อมูลเหล่านี้ถี่เกินและทำงานตลอดเวลา
ควร Update ตามความจำเป็น เช่น
ขณะอยู่รถ
หรือ
เมื่อ Heading/ตำแหน่งเปลี่ยนพอสมควร
แทน Query ข้อมูลจำนวนมากโดยไม่ใช้
51. Voice HUD ควร Poll ทุก Frame ไหม
ขึ้นกับ Voice Resource
ถ้า Voice System มี Events สำหรับ
Talking State
Voice Range
Radio State
สามารถให้ HUD Update จาก Events แทน Polling
ช่วยลด Work ซ้ำ
52. Hunger และ Thirst ควร Update ตาม Framework Event
ข้อมูล Roleplay Status มักไม่ได้เปลี่ยนทุก Frame
จึงเหมาะกับ
Status Change
→ HUD Update
มากกว่า Tick-based Query ที่ถี่มาก
53. อย่า Query Server ทุก Frame เพื่อ HUD
ข้อมูลอย่าง Money และ Job ไม่ควรถูก Request
Client → Server → Client
ทุก Game Tickเพียงเพื่อวาด HUD
ควรให้ Server/Framework ส่งข้อมูลเมื่อ State เปลี่ยน
ลด Network และ Script Work ที่ไม่จำเป็น
54. HUD กระตุกเพราะ Server Lag ได้ไหม
อาจดูเหมือนกัน แต่ต้องแยก
ถ้า
FPS ปกติ
แต่ Money/Hunger Update ช้า
อาจเป็น Data/Event Delay
แต่ถ้า
ทั้งภาพกระตุก
FPS ลด
เป็น Client Performance Problem มากกว่า
ใช้ cl_drawperf true ช่วยดูทั้ง FPS, Ping, Packet Loss, CPU และ GPU เพื่อแยกอาการได้ดีขึ้น.
55. Ping สูงไม่ได้หมายความว่า HUD ทำ FPS ตก
Ping เป็น Network Latency
FPS เป็น Rendering/Client Performance
cl_drawperf แสดง Metrics เหล่านี้แยกกัน.
จึงไม่ควรใช้คำว่า Lag รวมทุกอาการ
56. GPU 99% และ HUD ลด FPS
ถ้า GPU เต็มอยู่ก่อนแล้ว การเพิ่ม UI Rendering อาจทำให้ Frame Rate ลดได้ง่ายขึ้น
ในกรณีนี้ให้เปรียบเทียบ
HUD ON/OFF
GPU Usage
FPS
ด้วย cl_drawperf true.
แล้วค่อยตรวจ Effects/UI Rendering
57. CPU สูงและ HUD Resource สูง
ให้เน้น Client Script
เช่น
Loops
Natives
Framework Queries
Vehicle Calculations
แล้วใช้ Profiler หา Thread ที่กินเวลา
58. Profiler คือเครื่องมือสำคัญที่สุดเมื่อ resmon บอกว่า HUD หนัก
Cfx.re Profiler สามารถใช้ได้ทั้ง Client และ Server เพื่อระบุ Code/Threads ที่ทำให้ Performance มีปัญหา และ Guide ระบุว่า Client-side Profiler สามารถใช้ช่วยวิเคราะห์ FPS ได้.
59. เริ่ม Profiler อย่างไร
ใน F8 สามารถใช้
profiler record 500
เป็นจุดเริ่มต้นตามตัวอย่างในเอกสาร จากนั้นตรวจสถานะด้วย
profiler status
และดูผลด้วย
profiler view
ได้.
60. ทำไมต้อง Profile ตอนที่ HUD กระตุก
ถ้าบันทึกตอนยืนเฉย ๆ แต่ปัญหาเกิดตอนขับรถ
Profile จะไม่จับช่วงปัญหาหลัก
ดังนั้นควร Capture ตอน
เข้า Vehicle
HUD เปิด
FPS กำลังลด
Speedometer กำลัง Update
เพื่อให้เห็น Thread ที่ทำงานในช่วงนั้น
61. Profiler ดูอะไร
Cfx.re Profiler Guide ระบุว่าสามารถดู FPS Graph, CPU Time Graph และ Resource Tick Breakdown เพื่อหาช่วง Spike และ Script Threads ที่ทำงานใน Frame นั้น.
จึงเหมาะกับ Micro-stutter มากกว่าการเดาจาก Code
62. CPU Spike คืออะไร
ถ้าบาง Frame ใช้ CPU Time สูงผิดปกติ
อาจเห็น
FPS 120
↓
FPS 50
↓
กลับ 120
เป็นช่วงสั้น ๆ
Profiler ช่วยจับว่าช่วง Spike นั้น Thread ไหนทำงาน
63. Hitch Warning เกี่ยวกับ HUD ไหม
Cfx.re ระบุว่า Hitch Warnings บ่งชี้ว่า Resource บางตัวทำงานไม่ดี และตัวอย่างสาเหตุรวมถึง Unoptimized Loops หรือ SQL ที่ช้า โดย Profiler ใช้ช่วยตรวจได้.
HUD Client Resource มักไม่ควรทำ Heavy SQL เอง แต่ Loop ที่ไม่ Optimize เป็นเรื่องที่ควรตรวจ
64. while true โดยไม่มี Wait อันตรายมาก
Cfx.re ระบุชัดว่า while true do Loop ที่ไม่มี Wait สามารถทำให้ Client Crash ได้.
ดังนั้นทุก Continuous Thread ต้องมี Yield Path ที่ทำงานได้จริง
65. ระวัง Branch ที่ทำให้ Wait ไม่ถูกเรียก
ตัวอย่าง Logic ที่เขียนผิดอาจมีบาง State ที่ Skip Wait
ต้องตรวจทุก Branch
เป้าหมายคือ Continuous Loop ต้องไม่ Lock Script Execution
66. ใช้ Wait(5) แทน Wait(0) สำหรับทุกอย่างดีไหม
ไม่
Cfx.re ระบุว่างานที่ต้องทำทุก Frame ควรใช้ Wait(0) เพราะ Wait 5 หรือ 10 ms สามารถทำให้ Tick ถูกข้ามบนเครื่องที่มี FPS สูง.
ดังนั้นต้องตัดสินตามสิ่งที่ Code ต้องทำจริง
67. HUD Element ไหนต้องทุก Frameจริง
มีน้อยกว่าที่หลาย Resource คิด
ตัวอย่าง Element ที่อาจต้อง Responsive สูง
บาง Vehicle Indicators
บาง Reticle/Compass Effects
แต่
Job
Cash
Bank
Player ID
ไม่ต้องทุก Frame
68. ลด Resolution ของ HUD ช่วยไหม
NUI ไม่ได้ทำงานเหมือน Game Texture Pack โดยตรง
ปัญหาส่วนใหญ่ควรตรวจ
Rendering Effects
DOM
Images
Animations
Script
ก่อน
การลด Resolution หน้าจอทั้งเกมไม่ใช่ Root-cause Fix สำหรับ HUD Script ที่ Loop หนัก
69. รูปภาพใน HUD ใหญ่มากต้องระวังไหม
ควร Optimize Asset UI
เช่นไม่ใช้ภาพใหญ่เกินความละเอียดที่แสดงจริงโดยไม่มีเหตุผล
โดยเฉพาะ HUD ที่มี
Background Images
Animated Assets
Large Icons
จำนวนมาก
แต่ให้วัดผลก่อนและหลังเสมอ
70. Video Background ไม่เหมาะกับ Gameplay HUD ทั่วไป
HUD ที่ต้องอยู่บนจอตลอดเวลาควรหลีกเลี่ยง Media หนักที่ไม่มีประโยชน์ต่อ Gameplay
Loading Screen กับ Gameplay HUD มี Requirement คนละแบบ
อย่า Copy Design ของ Loading Screen มาทำ HUD ตลอดเวลาโดยไม่ประเมิน Performance
71. Custom Font หลาย Weight มีผลไหม
อาจเพิ่ม UI Assets และ Rendering Complexity บางส่วน
ควรโหลดเฉพาะ
Font Family
Weights
Styles
ที่ใช้งานจริง
แต่ไม่ควรคิดว่า Font เป็นสาเหตุหลักก่อนตรวจ Loop และ Message Frequency
72. CSS Blur ควรใช้อย่างระวัง
Effects เช่น
backdrop-filter
blur
large shadow
glow
บนพื้นที่ใหญ่และหลาย Elements อาจเพิ่ม Rendering Work
หาก GPU เป็น Bottleneck ให้ทดสอบปิด Effects เหล่านี้แบบ A/B
73. ปิด Animation ทั้งหมดเพื่อทดสอบ
ทำ Temporary Build
CSS Animation OFF
Transition OFF
แล้ววัด FPS
หากไม่ต่างกัน
อย่าเสียเวลา Optimize Animation ต่อ
ไปตรวจ Script/NUI Messages
74. Disable JavaScript Features ทีละส่วน
เช่น
Compass OFF
Voice OFF
Vehicle HUD OFF
Street Name OFF
แล้ววัด
ช่วยหาว่า Module ไหนเป็นต้นเหตุ
ดีกว่าลบ Code ทั้ง Resource
75. HUD Module ควรเปิด/ปิดแยกได้
Architecture ระยะยาวควรมี
Player HUD
Vehicle HUD
Compass
Voice
Status
เป็น Modules
ช่วยให้ A/B Test และ Debug ง่ายขึ้น
76. อย่ามี Speedometer สองตัวพร้อมกัน
Server อาจมี
custom_hud
+
standalone_speedometer
ทั้งสอง Query Vehicle Data อยู่พร้อมกัน
แม้ผู้เล่นจะเห็นเพียงตัวเดียว
ควรปิด Resource ซ้ำที่ไม่ใช้
77. Minimap Resource ก็อาจทำให้เข้าใจผิดว่า HUD หนัก
ถ้า Minimap/Compass Resource ถูก Start พร้อม HUD
ให้ทดสอบแยก
HUD
Minimap
Compass
Speedometer
เพราะชื่อ Resource ที่ผู้เล่นเรียกรวมว่า HUD อาจจริง ๆ เป็น 3–4 Resources
78. Voice Resource ก็ต้องแยก
Voice Icon อยู่ใน HUD
แต่ Voice Processing อาจเป็นคนละ Resource
หาก FPS/CPU เปลี่ยนเมื่อพูด ให้ตรวจทั้ง
HUD Voice Indicator
Voice Resource
ไม่ใช่โทษ Icon อย่างเดียว
79. Restart HUD แล้ว FPS ดีชั่วคราว
นี่เป็นเบาะแสสำคัญ
อาจมี
State สะสม
Object/List ไม่ถูก Clear
Event Handler ถูก Register ซ้ำ
Timer/Interval สะสม
หลังเล่นนาน
ต้องหาว่าทำไม Resource แย่ลงตามเวลา ไม่ควรใช้ Restart เป็นวิธีแก้ถาวร
80. JavaScript setInterval ซ้ำต้องระวัง
ถ้าเปิด/ปิด HUD แล้วสร้าง
setInterval(...)
ใหม่ทุกครั้งโดยไม่ Clear ของเดิม
หลังเปิด 10 ครั้งอาจมี 10 Timers ทำงานพร้อมกัน
ต้องมี Lifecycle ที่ชัด
81. Event Listener ซ้ำก็มีผล
ถ้า Code Register
window.addEventListener(...)
ซ้ำจาก Initialization หลายรอบ
Handler เดียวอาจถูกเรียกหลายครั้งต่อ Message
ตรวจ Resource/NUI Initialization ให้เกิดครั้งเดียวตามที่ตั้งใจ
82. Lua Event Handler ซ้ำได้เช่นกัน
ถ้า Resource Architecture Register Events ซ้ำจาก Function ที่ถูกเรียกหลายครั้ง
Data Update หนึ่งครั้งอาจทำงานหลายรอบ
Profiler และ Debug Counters ช่วยจับได้
83. เพิ่ม Counter เพื่อดู Message Frequency
ตัวอย่าง Debug ชั่วคราว
local messages = 0
CreateThread(function()
while true do
Wait(1000)
print('HUD messages/sec:', messages)
messages = 0
end
end)
แล้วเพิ่ม messages ทุกครั้งที่ส่ง HUD Message
จะทำให้เห็นว่า Resource ส่ง Message หลักสิบหรือหลักร้อยต่อวินาที
84. อย่าปล่อย Debug Counter ใน Production โดยไม่จำเป็น
ใช้เพื่อวิเคราะห์
เมื่อแก้เสร็จควรถอด Log ที่ไม่ต้องใช้
เพื่อลด Console Noise
85. FPS ตกเฉพาะผู้เล่นบางคน
ตรวจ Hardware และ Resolution เพิ่ม
HUD เดียวกันอาจมีผลแตกต่างกันระหว่าง
GPU รุ่นสูง
GPU รุ่นเก่า
1080p
4K
Ultrawide
ดังนั้น Production Test ควรมี Client หลายระดับ
86. ทดสอบ 4K สำคัญไหม
สำคัญถ้า Server มีผู้เล่นใช้ 4K
จำนวน Pixel ที่ UI/Game ต้อง Render มากกว่า 1080p มาก
HUD ที่ลื่นใน 1080p ไม่ควรถูกถือว่าลื่นทุก Resolution โดยไม่ทดสอบ
87. Ultrawide ก็ต้องทดสอบ
นอกจาก Performance ยังต้องตรวจ
Position
Scale
Element Count
Large Background Layers
ว่าไม่ได้ Render พื้นที่ใหญ่ผิดปกติ
88. เครื่องแรงไม่ควรใช้แทน Optimization
ถ้า Developer มี RTX ระดับสูงและ CPU แรงมาก
HUD ที่ไม่ Optimize อาจยังดูปกติ
แต่ผู้เล่นเครื่องกลางจะเห็นปัญหา
จึงควรทดสอบกับ Hardware หลายระดับ
89. วิธี Optimize แบบถูกลำดับ
อย่าแก้ทุกอย่างพร้อมกัน
ทำแบบนี้
Baseline
↓
หา Resource
↓
หา Thread/Module
↓
แก้ 1 จุด
↓
วัดใหม่
↓
บันทึกผล
ถ้าปรับ 10 อย่างพร้อมกัน คุณจะไม่รู้ว่าสิ่งใดได้ผลจริง
90. Workflow Debug HUD กระตุกแบบเร็วที่สุด
ขั้นที่ 1 — เปิด Performance Metrics
cl_drawperf true
FiveM แสดง FPS, Ping, Packet Loss, CPU และ GPU ผ่านคำสั่งนี้.
ขั้นที่ 2 — A/B Test HUD
HUD ON
HUD OFF
ขั้นที่ 3 — เปิด resmon
resmon true
ดู CPU/Memory ของ HUD Resource.
ขั้นที่ 4 — ถ้า HUD Resource CPU สูง
ตรวจ Client Loop และ Native Calls
ขั้นที่ 5 — ใช้ Profiler
profiler record 500
profiler status
profiler view
เพื่อหา Resource Tick/Thread ที่ทำให้ Frame Time Spike.
ขั้นที่ 6 — ถ้า Script ไม่หนัก
เปิด NUI Developer Tools
nui_devTools
เพื่อตรวจ JavaScript/DOM/CSS.
ขั้นที่ 7 — ปิด HUD Modules ทีละตัว
Vehicle
Compass
Voice
Status
ขั้นที่ 8 — ตรวจ Message Frequency
ดูว่า SendNUIMessage ถูกเรียกถี่เพียงใด.
ขั้นที่ 9 — แยก Fast/Slow/Event Data
ขั้นที่ 10 — วัด FPS ใหม่
ใช้สถานการณ์เดียวกับ Baseline
ตารางสรุป FiveM HUD กระตุกหรือ FPS ตก
| อาการ | จุดที่ควรตรวจ |
|---|---|
| FPS ลดทันทีเมื่อเปิด HUD | HUD/NUI Resource |
| resmon HUD สูง | Client Script |
| resmon ต่ำแต่ FPS ลด | NUI/UI/GPU |
| Speedometer กระตุกแต่ FPS ปกติ | Update Interval |
| เข้า Vehicle แล้ว FPS ลด | Vehicle HUD Loop |
| Money HUD หน่วง | Framework/Event |
| HUD กระตุกทุก Tick | Message/DOM Update |
| ปิด HUD แล้ว FPS กลับ | HUD Resource/Dependencies |
| Restart HUD แล้วดีชั่วคราว | State/Timer/Event Leak |
| FPS Spike เป็นช่วง ๆ | Profiler |
| GPU สูง | UI Effects/Game Rendering |
| CPU สูง | Script/Native Calls |
| ผู้เล่นบางคนหนัก | Hardware/Resolution |
| 4K หนักกว่า 1080p | UI/Game Rendering Load |
| HUD Settings หนัก | NUI Settings UI |
| Compass หนัก | Update Calculation |
| Voice HUD หนักตอนพูด | HUD + Voice Resource |
Checklist Client Script
☐ ไม่มี while true ที่ขาด Wait
☐ ไม่ Query ทุกข้อมูลทุก Frame
☐ Vehicle Logic ทำเฉพาะเมื่อจำเป็น
☐ Money ใช้ Event
☐ Job ใช้ Event
☐ Cache ค่าที่เหมาะสม
☐ ไม่ส่ง NUI Message เดิมซ้ำ
☐ ไม่มี Duplicate Threads
☐ ไม่มี Duplicate Events
☐ Restart Resource แล้ว State ไม่ซ้ำ
Cfx.re ระบุว่า Continuous Loop ต้องมี Wait และแนะนำหลีกเลี่ยง Heavy Native Calls แบบ Per-tick รวมถึง Cache Native Results ที่เปลี่ยนไม่บ่อยเมื่อเหมาะสม.
Checklist NUI
☐ Message Handler มีเพียงที่ต้องใช้
☐ ไม่มี console.log ทุก Message ใน Production
☐ ไม่ Render DOM ทั้งหน้าโดยไม่จำเป็น
☐ Update เฉพาะค่าที่เปลี่ยน
☐ Timer ไม่ถูกสร้างซ้ำ
☐ Event Listener ไม่ถูก Register ซ้ำ
☐ CSS Animation เท่าที่จำเป็น
☐ Effects หนักผ่าน A/B Test
☐ Modules แยก State
☐ Settings UI Cleanup ถูก
Checklist Performance Test
☐ จด FPS ก่อนแก้
☐ จด FPS หลังแก้
☐ ใช้สถานที่เดียวกัน
☐ รถคันเดียวกัน
☐ HUD State เดียวกัน
☐ ทดสอบเดิน
☐ ทดสอบขับรถ
☐ ทดสอบผู้เล่นหลายคน
☐ ทดสอบ 1080p
☐ ทดสอบ Resolution สูง
☐ ตรวจ resmon
☐ ตรวจ profiler
ตัวอย่าง HUD Code ที่ควรระวัง
CreateThread(function()
while true do
Wait(0)
local ped = PlayerPedId()
local vehicle = GetVehiclePedIsIn(ped, false)
SendNUIMessage({
health = GetEntityHealth(ped),
armor = GetPedArmour(ped),
money = currentMoney,
job = currentJob,
speed = GetEntitySpeed(vehicle),
fuel = currentFuel
})
end
end)
ปัญหาคือ Loop นี้กำลังพยายามอัปเดตทุกอย่างทุก Game Tick แม้ว่าหลายค่าจะไม่เปลี่ยน
ตัวอย่างแนวคิดที่ดีกว่า
แยก Player State
CreateThread(function()
local lastHealth
local lastArmor
while true do
Wait(100)
local ped = PlayerPedId()
local health = GetEntityHealth(ped)
local armor = GetPedArmour(ped)
if health ~= lastHealth or armor ~= lastArmor then
lastHealth = health
lastArmor = armor
SendNUIMessage({
action = 'playerStatus',
health = health,
armor = armor
})
end
end
end)
และแยก Vehicle State
CreateThread(function()
while true do
local sleep = 1000
local ped = PlayerPedId()
if IsPedInAnyVehicle(ped, false) then
sleep = 50
local vehicle = GetVehiclePedIsIn(ped, false)
SendNUIMessage({
action = 'vehicle',
speed = GetEntitySpeed(vehicle)
})
end
Wait(sleep)
end
end)
ตัวเลข Interval เป็นเพียงตัวอย่าง ต้องปรับตาม HUD จริง
Money ควรทำแบบ Event-driven
แนวคิด
RegisterNetEvent('hud:updateMoney', function(money)
SendNUIMessage({
action = 'money',
value = money
})
end)
แทน Loop Query Money ต่อเนื่อง
ช่วยให้ HUD ทำงานเฉพาะเมื่อข้อมูลเปลี่ยน
Job ก็ใช้แนวคิดเดียวกัน
RegisterNetEvent('hud:updateJob', function(job)
SendNUIMessage({
action = 'job',
value = job
})
end)
Resource Framework จริงอาจมี Events คนละชื่อ
ควรใช้ API/Event ของ Framework ที่ติดตั้งอยู่จริง
อย่า Optimize โดยลด Refresh Rate จน HUD ใช้งานไม่ได้
Speedometer ที่ Update ทุก 500 ms อาจใช้ CPU ต่ำลง
แต่ผู้เล่นจะเห็น
40
↓
65
↓
91
แบบกระโดด
เป้าหมายต้องสมดุลระหว่าง
Responsiveness
Performance
อย่าใช้ค่าจาก resmon เพียงตัวเดียวตัดสิน
ควรดูร่วมกับ
FPS
CPU
GPU
Profiler
Actual Gameplay
เพราะ Resource CPU ต่ำไม่ได้พิสูจน์ว่า NUI Rendering ไม่มีผลต่อ FPS
อย่าโทษ HUD ถ้าทุก Resource กระตุก
ถ้า HUD OFF แล้วยัง FPS ตก
ให้ขยายการตรวจไปยัง
Map
MLO
Vehicles
Scripts
Peds
Voice
HUD อาจเพียงแสดงอาการในช่วงเดียวกัน ไม่ใช่ Root Cause
อย่าลดกราฟิกก่อนพิสูจน์ HUD
ถ้า
HUD ON = 70 FPS
HUD OFF = 120 FPS
ใน Test Environment เดียวกัน
นี่เป็นสัญญาณให้ตรวจ HUD ก่อนลด Texture/Graphics ของผู้เล่นทั้งหมด
สิ่งที่ไม่ควรทำกับ FiveM HUD
หลีกเลี่ยง
SendNUIMessage ทุกข้อมูลทุก Frame
Query Money ทุก Frame
Query Job ทุก Frame
ทำ Vehicle Calculation ตอนเดิน
ใช้ while true โดยไม่มี Wait
สร้าง setInterval ซ้ำ
Register Event Listener ซ้ำ
Update DOM ทั้งหน้าเมื่อเปลี่ยนค่าเดียว
เปิด Effects หนักโดยไม่วัดผล
เปลี่ยน HUD ทั้งตัวก่อนใช้ resmon/profiler
สูตรจำง่ายสำหรับ Optimize HUD
MEASURE
↓
FIND
↓
REDUCE
↓
CACHE
↓
EVENT
↓
RENDER
↓
MEASURE AGAIN
อย่าเริ่มจากเดาว่าปัญหาอยู่ตรงไหน
สรุป FiveM HUD กระตุกหรือทำให้ FPS ตก แก้อย่างไร
ถ้า FiveM HUD กระตุกหรือทำให้ FPS ตก ให้เริ่มจากพิสูจน์ก่อนว่า HUD เป็นสาเหตุจริง
เปิด
cl_drawperf true
เพื่อดู FPS, Ping, Packet Loss, CPU และ GPU แล้วทำ A/B Test ระหว่าง HUD ON และ HUD OFF.
จากนั้นใช้
resmon true
เพื่อดูว่า HUD Resource ใช้ CPU หรือ Memory สูงผิดปกติหรือไม่ เพราะ Cfx.re ระบุว่า Resource Monitor ถูกออกแบบมาเพื่อช่วยหา Resources ที่ใช้เวลาประมวลผลสูงบน Client.
ถ้า HUD Resource ใช้ CPU สูง ให้ตรวจ
while true
Wait
Native Calls
Vehicle Calculations
Framework Queries
โดย Cfx.re ระบุว่า Loop ต่อเนื่องต้องมี Wait, งานที่จำเป็นต้องทำทุก Frameสามารถใช้ Wait(0) ได้ แต่ควรหลีกเลี่ยง Heavy Native Calls ทุก Tick และ Cache ข้อมูลที่เหมาะสม.
ถ้าต้องการเจาะลึกว่า Thread ไหนเป็นต้นเหตุ ใช้
profiler record 500
profiler status
profiler view
เพื่อ Capture และดู CPU Time/Resource Tick ของช่วงที่ FPS Drop.
หาก Client Script ไม่ได้หนักมาก แต่เปิด HUD แล้ว FPS ยังลด ให้ตรวจฝั่ง NUI เพราะ FiveM Fullscreen NUI เป็น UI Overlay และ Script สามารถส่ง Message ไปยัง NUI ผ่าน SendNUIMessage.
ควรลดการส่งข้อมูลซ้ำ เช่น
Money
Job
Player ID
ที่ไม่เปลี่ยนทุก Frame และเปลี่ยนเป็น Event-driven หรือ Change-driven Updates
ส่วนข้อมูลอย่าง Speed หรือ RPM สามารถ Update ถี่กว่า แต่ควรทำเฉพาะเมื่อผู้เล่นอยู่ใน Vehicle และไม่ควรบังคับให้ข้อมูล HUD ทุกประเภทใช้ Refresh Rate เดียวกัน
สำหรับ JavaScript ให้หลีกเลี่ยงการ Update DOM ทั้งหน้าเมื่อเปลี่ยนเพียงค่าเดียว ลด Timer/Event Listener ที่ซ้ำ และทดสอบ Effects อย่าง Blur, Shadow หรือ Continuous Animation แบบ A/B
หากต้อง Debug ฝั่ง NUI FiveM เปิด CEF Developer Tools ได้ผ่าน nui_devTools ใน F8 เมื่อ Developer Mode พร้อมใช้งาน.
แนวทางของ comsiam คืออย่า Optimize HUD จากความรู้สึก แต่ให้ใช้ FPS → resmon → Profiler → NUI DevTools ไล่จากภาพรวมลงไปหา Code หรือ UI Module ที่เป็นต้นเหตุจริง จากนั้นค่อยลด Loop, Cache State, ใช้ Events และ Render เฉพาะข้อมูลที่เปลี่ยน วิธีนี้จะรักษาความลื่นของ HUD โดยไม่ต้องทำให้ Speedometer หน่วงหรือถอดฟีเจอร์ที่ผู้เล่นใช้งานจริงออกทั้งหมด
Comments
Post a Comment