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 ลดทันทีเมื่อเปิด HUDHUD/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 กระตุกทุก TickMessage/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 หนักกว่า 1080pUI/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

Popular posts from this blog

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

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

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