QBCore Script ไม่ทำงาน แก้อย่างไร

QBCore Script ไม่ทำงานสามารถเกิดได้ตั้งแต่ qb-core ไม่ Start, oxmysql เชื่อม Database ไม่ได้, Resource Start Order ผิด, Script ใช้ QBCore API คนละ Version, PlayerData ยังไม่โหลด ไปจนถึง Inventory หรือ Target ไม่ตรงกับที่ Script รองรับ

อาการที่พบบ่อย เช่น

QBCore = nil
No such export GetCoreObject
attempt to index a nil value
Player is nil
PlayerData is nil
Callback ไม่ตอบ
Job ไม่ทำงาน
Item ไม่เข้า
Target ไม่ขึ้น
Menu ไม่เปิด
Database Error

วิธีแก้ที่ถูกต้องควรไล่จาก Core ไปหา Script ลูกตามลำดับ

oxmysql
↓
qb-core
↓
Player Loading
↓
Resource Dependency
↓
QBCore Integration
↓
Inventory / Target
↓
Database
↓
Client / Server Logic

อย่าเริ่มด้วยการล้าง Cache, Reinstall Windows หรือเปลี่ยน Framework ทั้ง Server ก่อนรู้ว่า Error จริงเกิดจากอะไร

① ตรวจว่า qb-core Start สำเร็จหรือไม่

สิ่งแรกที่ต้องดูคือ

qb-core

เปิด Server Console แล้วตรวจว่า Resource Start สำเร็จหรือมี Error

สามารถทดสอบด้วย

ensure qb-core

หาก qb-core เองยัง Error ให้แก้ Core ก่อน Script ลูก

เพราะ Architecture เป็น

qb-core
↓
qb-policejob
qb-inventory
qb-banking
qb-garages
Custom QB Scripts

ถ้า Core ล้ม Scripts จำนวนมากสามารถพังพร้อมกันได้

② ถ้าหลาย QBCore Script พังพร้อมกันให้สงสัย Core ก่อน

สมมติพร้อมกันเกิด

Police ใช้ไม่ได้
Garage ใช้ไม่ได้
Bank ใช้ไม่ได้
Job ใช้ไม่ได้
Phone Error

โอกาสที่ Script ทั้ง 5 ตัวเสียพร้อมกันมีน้อยกว่าปัญหาที่

qb-core
Database
Dependency กลาง

ให้ตรวจ Common Dependency ก่อน

นี่คือวิธี Root Cause Analysis ที่ช่วยประหยัดเวลามาก

③ ตรวจ oxmysql

Current qb-core ใช้

oxmysql

เป็น Database Dependency

ดังนั้นตรวจว่า

oxmysql

Start สำเร็จและเชื่อม Database ได้

ถ้า Console มีข้อความประเภท

Access denied
Unknown database
Connection refused
Unable to connect

ให้แก้ Database ก่อน

QBCore Script จำนวนมากอาจ Error ต่อเนื่องเพราะ Player Data โหลดไม่สมบูรณ์

④ ตรวจ mysql_connection_string

ใน server.cfg จะมีค่าประมาณ

set mysql_connection_string "mysql://user:password@localhost/qbcore?charset=utf8mb4"

ตรวจ

Username
Password
Host
Database Name
Port

ให้ถูกต้อง

อย่าลืมว่า Password ที่มีอักขระพิเศษบางชนิดอาจต้องจัดการให้เหมาะกับ Connection String

ถ้า Database Connection ผิด อย่าไปแก้ qb-core Source ก่อน

⑤ ตรวจ Start Order

QBCore Script ที่ใช้ Core ต้อง Start หลัง Dependency พร้อม

แนวคิด

ensure oxmysql
ensure qb-core
ensure my-qb-script

ถ้า Script ต้องใช้ Resource เพิ่ม เช่น

qb-target
qb-inventory

ก็ต้องจัดตาม Dependency จริง

ตัวอย่าง

ensure oxmysql
ensure qb-core
ensure qb-target
ensure qb-inventory
ensure my-job

ไม่จำเป็นว่าทุก Server ต้องใช้ลำดับนี้เหมือนกัน แต่ Dependency ต้องพร้อมก่อน Resource ที่เรียกมัน

⑥ ใช้ได้หลัง restart แต่ตอน Boot ใช้ไม่ได้

นี่เป็นอาการคลาสสิกของ

Start Order
หรือ
Initialization Timing

เช่น

Server Boot
↓
my-job Start
↓
qb-core ยังไม่พร้อม
↓
Error

แต่หลัง Server เปิดครบแล้วสั่ง

restart my-job

กลับใช้ได้

ควรแก้ Dependency และ Start Order

ไม่ควรแก้ด้วย

Wait(10000)

แบบสุ่มเป็นวิธีหลัก เพราะแค่ซ่อน Architecture Problem

⑦ ตรวจ fxmanifest.lua

เปิด

my-script/fxmanifest.lua

แล้วตรวจ

client_scripts
server_scripts
shared_scripts
dependencies

ตัวอย่าง Script ที่ต้องใช้ QBCore อาจประกาศ

dependency 'qb-core'

หรือเรียก Core จาก Script โดยตรง

ถ้ามี Dependency อย่าง

ox_lib
qb-target
qb-inventory

ต้องมี Resource เหล่านั้นจริงด้วย

⑧ QBCore Object ดึงอย่างไรใน Script ปัจจุบัน

รูปแบบมาตรฐานที่พบใน QBCore ปัจจุบันคือ

local QBCore = exports['qb-core']:GetCoreObject()

จากนั้นใช้

QBCore.Functions
QBCore.Shared

ตามที่ Script ต้องการ

ถ้า Script ขึ้นว่า

No such export GetCoreObject

ควรตรวจ

qb-core Started?
Folder ชื่อ qb-core?
Core Version ถูก?
Resource ถูกแก้หรือไม่?

ก่อน

⑨ อย่าเปลี่ยนชื่อ qb-core

Script จำนวนมากเรียก Core ด้วยชื่อ

exports['qb-core']:GetCoreObject()

ดังนั้นถ้า Rename Folder

qb-core

เป็น

my-core

Resource เหล่านั้นจะหา Core ไม่เจอ

Core Resource ควรใช้ชื่อ Original เว้นแต่คุณควบคุมและแก้ Integration ทุกตัวได้จริง

⑩ QBCore = nil เกิดจากอะไร

ถ้า Error

attempt to index a nil value (global 'QBCore')

หรือ

QBCore is nil

ให้ตรวจว่า Script มีการ Initialisation Core หรือไม่

เช่น

local QBCore = exports['qb-core']:GetCoreObject()

และไฟล์นั้นถูกโหลดจริงหรือไม่

อีกสาเหตุคือ Script แยกหลายไฟล์ แล้วประกาศ

local QBCore

ไว้ในไฟล์หนึ่ง แต่พยายามใช้จากอีกไฟล์หนึ่งโดยคิดว่า Local Variable ถูก Share

Local Variable ไม่ได้ Shared ระหว่างไฟล์โดยอัตโนมัติแบบนั้น

⑪ GetCoreObject สามารถเลือกเฉพาะข้อมูลที่ต้องใช้ได้

Current QBCore รองรับการกรอง Object ที่ต้องการ

ตัวอย่าง

local QBCore = exports['qb-core']:GetCoreObject({
    'Functions'
})

หรือ

local QBCore = exports['qb-core']:GetCoreObject({
    'Functions',
    'Shared'
})

ช่วยไม่ต้องนำ Core Object ทุกส่วนเข้ามาหาก Resource ต้องการเพียงบางส่วน

แต่ Script รุ่นเก่าที่ใช้

exports['qb-core']:GetCoreObject()

ทั้งก้อนยังเป็น Pattern ที่พบได้

⑫ Script เก่าอาจใช้ QBCore Object คนละ Pattern

QBCore มีการพัฒนา API มาหลายรุ่น

ถ้า Download Script อายุหลายปีแล้วเกิด

Core Object nil
Function ไม่มี
Export ไม่มี

อย่าแก้ Core ให้ย้อนกลับไปหารุ่นเก่าทันที

ควรตรวจว่า Developer มี

Current Version
Migration
Updated Branch

หรือไม่

Resource ใหม่มักเหมาะกับ Current QBCore มากกว่า Script เก่าที่ถูก Patch ต่อกันหลายปี

⑬ Player Object เป็น nil

Server-side Script มักใช้

local Player = QBCore.Functions.GetPlayer(source)

if not Player then
    return
end

หาก Player เป็น nil อาจเกิดจาก

Player ยังไม่ Load
source ผิด
Player Disconnect แล้ว
Event Timing ผิด
Code ทำงานนอก Player Context

ไม่ควรทำต่อทันทีด้วย

Player.PlayerData

โดยไม่เช็ก Player ก่อน

⑭ ตัวอย่าง Server Event ที่ปลอดภัยกว่า

RegisterNetEvent('myjob:server:start', function()
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)

    if not Player then
        return
    end

    print(Player.PlayerData.citizenid)
end)

Flow คือ

Client
↓
Server Event
↓
source
↓
GetPlayer
↓
ตรวจ Player
↓
ทำงาน

ช่วยป้องกัน Error จากการเรียก Player Object ที่ไม่มีอยู่

⑮ PlayerData เป็น nil ฝั่ง Client

Client Script อาจทำ

local PlayerData = QBCore.Functions.GetPlayerData()

แต่ถ้า Code ทำงานก่อน Character โหลดเสร็จ ข้อมูลบางส่วนอาจยังไม่พร้อม

โดยเฉพาะ Script ที่ใช้

PlayerData.job.name

ทันทีตอน Resource Start

อาจเกิด

attempt to index a nil value

ได้

ต้องรองรับ Player Loading Lifecycle

⑯ ใช้ OnPlayerLoaded เมื่อจำเป็น

QBCore มี Client Event

QBCore:Client:OnPlayerLoaded

สำหรับบอกว่า Player โหลดเข้า Server หลัง Character Selection สำเร็จแล้ว

ตัวอย่าง

RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
    local PlayerData = QBCore.Functions.GetPlayerData()

    print(PlayerData.citizenid)
end)

เหมาะกับการ Initialize Feature ที่ต้องใช้ PlayerData

⑰ Player Logout ต้องจัดการ State ด้วย

มี Event

QBCore:Client:OnPlayerUnload

เมื่อ Player Logout กลับ Character Selection

ถ้า Script เก็บ State เช่น

PlayerData
Job
Zones
Blips
NPC
UI

ควร Cleanup ตาม Architecture

ไม่เช่นนั้น Character ใหม่อาจได้รับ State จาก Character เดิม

⑱ QBCore:Player:SetPlayerData คืออะไร

เมื่อ Player Data เปลี่ยน QBCore มี Event

QBCore:Player:SetPlayerData

Script สามารถใช้ Update Local PlayerData ได้

ตัวอย่าง

RegisterNetEvent('QBCore:Player:SetPlayerData', function(val)
    PlayerData = val
end)

ถ้า Script Cache PlayerData แค่ตอนเข้า Serverแต่ไม่อัปเดตภายหลัง Job/Money/Metadata อาจกลายเป็นข้อมูลเก่า

⑲ เปลี่ยน Job แล้ว Script ยังคิดว่า Job เก่า

ตัวอย่าง

เข้า Server
→ unemployed

Admin เปลี่ยน Job
→ police

Script ยังคิดว่า
→ unemployed

ปัญหาอาจเกิดจาก Script Cache

PlayerData.job

ไว้ตอนเริ่มแล้วไม่ Handle Update

QBCore มี Job Update Flow ดังนั้น Script ควรอัปเดต State เมื่อ Job เปลี่ยน

⑳ OnJobUpdate ใช้ทำอะไร

QBCore มี Client Event

QBCore:Client:OnJobUpdate

สำหรับแจ้ง Job ใหม่

Script สามารถใช้แนวคิด

RegisterNetEvent('QBCore:Client:OnJobUpdate', function(job)
    PlayerData.job = job
end)

จากนั้น Interaction ต่าง ๆ จะใช้ Job ล่าสุด

เหมาะกับ

Police
EMS
Mechanic
Job Zones
Blips
Duty
Boss Menu

㉑ Job Name ไม่ตรงทำให้ Script ไม่ทำงาน

สมมติ Config ระบุ

Config.Job = 'police'

แต่ Shared Jobs ใช้

lspd

Condition

PlayerData.job.name == Config.Job

ก็จะไม่ผ่าน

ตรวจชื่อ Job จริง

QBCore.Shared.Jobs

และ PlayerData

อย่าแก้ Script ก่อนเช็ก String ง่าย ๆ จุดนี้

㉒ Grade ไม่ตรงก็ทำให้ Feature หาย

บาง Script ตรวจ

Job = police
Grade >= 3

Player อาจเป็นตำรวจจริง แต่ Grade ต่ำกว่าที่ Config กำหนด

ผลคือ

Boss Menu ไม่ขึ้น
Armory บางส่วนไม่ขึ้น
Management ไม่เปิด

ตรวจ

PlayerData.job.grade
PlayerData.job.isboss

ตาม Script Version ที่ใช้

㉓ Job ไม่มีใน Shared Jobs

QBCore มี Shared Jobs Definitions

หาก Script ตั้ง

police2

แต่ QBCore ไม่มี Job นี้ Resource อาจ

  • ไม่ให้ SetJob

  • ได้ข้อมูล Default

  • Error เมื่ออ่าน Grade

  • ไม่ผ่าน Condition

ต้องเพิ่ม Job ด้วย Structure ที่ถูกต้อง

ไม่ใช่เพิ่มเพียงชื่อ Job ใน Database แล้วคาดว่า Shared Data จะรู้เองเสมอ

㉔ Item ไม่มีใน Shared Items

Script อาจต้องใช้

repairkit
lockpick
radio

ถ้า Item Definition ไม่มี ระบบ Inventory/Script อาจ Error

ตรวจ

QBCore.Shared.Items

หรือ Shared Item Source ของ Version ที่ใช้

โดยเฉพาะ Script ใหม่ที่มาพร้อมรายการ

Required Items

ต้องเพิ่มให้ครบ

㉕ อย่าใช้ชื่อ Item ต่างกัน

ตัวอย่าง Script Config

Config.RequiredItem = 'water'

แต่ QBCore มี

water_bottle

ระบบจะมองเป็นคนละ Item

เช่นเดียวกับ

repairkit
advancedrepairkit

ต้องใช้ Internal Name ตรงกัน ไม่ใช่ Label ที่แสดงให้ Player เห็น

㉖ Callback ไม่ทำงาน

QBCore มีระบบ Callback

ฝั่ง Server Register

QBCore.Functions.CreateCallback('myScript:getData', function(source, cb)
    cb({
        success = true
    })
end)

ฝั่ง Client

QBCore.Functions.TriggerCallback('myScript:getData', function(data)
    print(data.success)
end)

ถ้าไม่ตอบ ให้ตรวจ

Callback Name
Server File ถูกโหลด?
CreateCallback ทำงาน?
Server Error?
Resource Started?

㉗ Callback Name ต้องตรงทุกตัว

Client

QBCore.Functions.TriggerCallback(
    'garage:getVehicles',
    function(data)
    end
)

Server

QBCore.Functions.CreateCallback(
    'garage:getVehicle',
    function(source, cb)
    end
)

ต่างกันที่

getVehicles
getVehicle

จึงไม่ใช่ Callback เดียวกัน

ควร Copy Name จากต้นทางแทนการพิมพ์ใหม่หลายจุด

㉘ Callback บาง Path ไม่เรียก cb

ตัวอย่าง

QBCore.Functions.CreateCallback('shop:getData', function(source, cb)
    local Player = QBCore.Functions.GetPlayer(source)

    if not Player then
        return
    end

    cb(data)
end)

ถ้า Framework/Script คาดหวัง Response การออกจาก Function โดยไม่มี Response อาจทำให้ฝั่ง Client รอหรือจัดการไม่ถูก

ออกแบบ Response ให้ชัดเจน เช่น

if not Player then
    cb(nil)
    return
end

ตามรูปแบบของ Script

㉙ Event ไม่ทำงาน

ตรวจ Event Name

Client

TriggerServerEvent('myjob:server:start')

Server

RegisterNetEvent('myjob:server:start', function()

ต้องตรงกัน

จากนั้นใช้

print('client sent')

และ

print('server received')

ชั่วคราวเพื่อดูว่า Flow หยุดตรงไหน

㉚ อย่าเชื่อค่าที่ Client ส่งมา

ตัวอย่างที่ไม่ปลอดภัย

RegisterNetEvent('job:server:reward', function(amount)
    local Player = QBCore.Functions.GetPlayer(source)

    Player.Functions.AddMoney('cash', amount)
end)

Client สามารถพยายามส่ง

amount = 99999999

ได้

Framework ไม่ได้ทำให้ Client Input ปลอดภัยอัตโนมัติ

Server ควรกำหนด Reward เองหลัง Validate Gameplay State

㉛ ตัวอย่าง Reward ที่ดีกว่า

RegisterNetEvent('job:server:complete', function()
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)

    if not Player then
        return
    end

    -- ตรวจ Job
    -- ตรวจ State
    -- ตรวจ Position
    -- ตรวจ Cooldown

    local reward = 500

    Player.Functions.AddMoney('cash', reward)
end)

หลักคือ

Client
→ แจ้ง Action

Server
→ ตรวจ

Server
→ กำหนด Reward

ไม่ใช่ให้ Client เป็น Source of Truth

㉜ Money ไม่เพิ่ม

ถ้า

Player.Functions.AddMoney

ไม่เกิดผล ให้ตรวจ

  • Player Object มีหรือไม่

  • Money Type ถูกหรือไม่

  • Amount ถูก Type หรือไม่

  • Function ถูกเรียกจริงหรือไม่

  • Server Error หรือไม่

ตัวอย่าง Money Type ที่ Config อาจมี

cash
bank
crypto

แต่ต้องดู QBCore Configuration ของ Server จริง

㉝ Money Type ผิด

ตัวอย่าง

Player.Functions.AddMoney('wallet', 500)

แต่ Server ไม่มี Account

wallet

อาจไม่ทำงานตามที่คาด

ตรวจ

QBCore.Config.Money.MoneyTypes

หรือ Current Config ของ Framework

อย่าเดาชื่อ Account จาก Label ใน UI

㉞ SetJob ไม่ทำงาน

ตัวอย่าง

Player.Functions.SetJob('police', 1)

ต้องมี

police

ใน Shared Jobs และ Grade

1

ต้องถูกต้องตาม Data Structure

หาก Job ไม่มี SetJob อาจคืน Failure หรือข้อมูลไม่เป็นตามที่ต้องการ

ตรวจทั้ง Job Name และ Grade

㉟ SetGang ไม่ทำงาน

ใช้หลักเดียวกับ Job

ตัวอย่าง

Player.Functions.SetGang('ballas', 1)

ต้องมี Gang Definition

ballas

และ Grade ที่ถูกต้อง

อย่าคิดว่าเพิ่ม Gang Name ใน Custom Script อย่างเดียวแล้ว QBCore จะรู้จักโดยอัตโนมัติ

㊱ Metadata ไม่อัปเดต

QBCore มี Player Functions สำหรับ Metadata

ตัวอย่างแนวคิด

Player.Functions.SetMetaData('stress', 10)

หาก Metadata ไม่เปลี่ยน ให้ตรวจ

Player Object
Key
Type
Event Flow
PlayerData Update

และดูว่ามี Resource อื่นเขียนค่าทับภายหลังหรือไม่

㊲ Script เปิดได้แต่ Item ไม่เข้า

นี่ช่วยจำกัดปัญหาได้

ถ้า UI และ Interaction ทำงาน แปลว่า Client Layer อาจปกติ

ให้ตรวจ Server → Inventory

Player Action
↓
Server Event
↓
Inventory
↓
Add Item

ปัญหาอาจอยู่ที่

Inventory API
Item Name
Weight
Slots
Version

ไม่ใช่ QBCore Core

㊳ Script ใช้ qb-inventory แต่ Server ใช้ Inventory อื่น

นี่เป็นปัญหายอดนิยม

Script อาจเรียก

qb-inventory

โดยตรง

แต่ Server เปลี่ยนเป็น Inventory ใหม่

ผลคือ

Item ไม่เข้า
Stash ไม่เปิด
Shop พัง
Crafting ไม่ทำงาน

แม้ Script จะเขียนว่า

QBCore Compatible

ก็ตาม

Framework Compatibility กับ Inventory Compatibility เป็นคนละเรื่อง

㊴ HasItem ไม่ทำงานควรตรวจ Inventory

QBCore Documentation ปัจจุบันระบุว่าฟังก์ชัน HasItem ใน Player Function เป็น Routing ไป Inventory และแนะนำให้ใช้ Inventory Export โดยตรงในบริบทที่เหมาะสม

ดังนั้นถ้า Item Check พังหลังเปลี่ยน Inventory ให้ตรวจ Inventory Integration ก่อน

ไม่ควรแก้ PlayerData แบบสุ่ม

㊵ Script ใช้ qb-target แต่ Server ใช้ ox_target

อาการมักเป็น

Script Start
NPC มี
แต่ Target Option ไม่ขึ้น

ตรวจ Config เช่น

Config.Target = 'qb-target'

และ Resource จริง

ถ้า Script ไม่มี ox_target Bridge การลง ox_target อย่างเดียวไม่ได้ทำให้ QB Target API ถูกแปลงอัตโนมัติ

ต้องใช้ Version ที่รองรับหรือเขียน Bridge

㊶ qb-target ไม่ Start

ถ้า Script พึ่ง

qb-target

ตรวจ

ensure qb-target

และ Server Console

รวมถึงตรวจว่า Resource ถูกโหลดก่อน Script ลูก

ถ้ามี Error ใน qb-target เอง ให้แก้ Target ก่อน Job/Shop Script ที่พึ่งมัน

㊷ Script ใช้ ox_lib แต่ไม่มี ox_lib

QBCore Script สมัยใหม่บางตัวใช้

ox_lib

แม้ Core จะเป็น QBCore

อาจเห็นใน Manifest

shared_script '@ox_lib/init.lua'

ถ้าไม่มี ox_lib

Resource อาจไม่ทำงานหรือ Error ตั้งแต่ Start

คำว่า QBCore Script ไม่ได้หมายความว่าใช้เฉพาะ qb-* Resources เท่านั้น

㊸ Missing dependency แก้อย่างไร

ถ้า Console แจ้ง

Missing dependency some_resource

ให้แก้ Resource นั้นตรง ๆ

ตรวจ

Folder มี?
ชื่อ Folder ตรง?
fxmanifest.lua มี?
Resource Start ได้?
Version ถูก?

อย่าลบ

dependency 'some_resource'

จาก Manifest เพียงเพื่อทำให้ Error หาย ถ้า Code ยังต้องเรียก Dependency นั้น

㊹ No such export แก้อย่างไร

ตัวอย่าง

No such export SomeFunction in resource qb-inventory

ตรวจ

Export Name
Resource Version
Resource Name
Client/Server Side
Dependency Started

Script อาจถูกเขียนสำหรับ qb-inventory คนละ Version

หรือ Developer เปลี่ยน API แล้ว Config/Bridge ของ Scriptยังเก่า

㊺ Table doesn't exist

ถ้า Server Console แจ้ง

Table 'qbcore.my_table' doesn't exist

แปลว่า Script Query Table ที่ไม่มี

ตรวจ Script Package ว่ามี

install.sql
database.sql
migration.sql

หรือไม่

Import SQL ให้ตรง Version

อย่าสร้าง Table จากชื่อ Error อย่างเดียว

㊻ Unknown column

ตัวอย่าง

Unknown column 'garage_id'

แสดงว่า Script กับ Database Schema ไม่ตรงกัน

อาจเกิดจาก

Update Script
แต่ไม่ได้ Import Migration

Database เก่า
Script ใหม่

SQL คนละ Version

ตรวจ Changelog และ Migration ของ Resource ก่อนเพิ่ม Column เอง

㊼ Duplicate column / Table already exists

มักเกิดจาก Import SQL ซ้ำ

อย่า Import SQL ทุกครั้งที่ Script Error

ก่อน Import ให้ตรวจ Database ว่า

Table มีแล้ว?
Column มีแล้ว?
Migration เคยรันแล้ว?

และ Backup Database ก่อนแก้ Schema ของ Production Server

㊽ Menu ไม่เปิด

ถ้า Script Start แต่ Menu ไม่เปิด ให้ดู

F8

ฝั่ง Client

ปัญหาอาจเป็น

NUI Error
Client Lua Error
Target Error
Menu Dependency Missing
PlayerData nil

ถ้า Server Console สะอาด แต่ F8 มี Error ชัด ให้ Debug Client ก่อน

㊾ NUI เปิดจอดำ

ตรวจ

ui_page
files
HTML
JavaScript
CSS
NUI Callback

และ Browser/NUI Errors

QBCore Framework ไม่ได้เป็นสาเหตุของ NUI ทุก Error

แยก Layer

QBCore
≠
NUI

ให้ชัด

㊿ Notification ไม่ขึ้นแต่ระบบทำงาน

ตัวอย่าง

เงินถูกหัก
Item เข้า
แต่ไม่มีข้อความ

นี่อาจเป็น Notification Integration Problem เท่านั้น

ตรวจ

QBCore.Functions.Notify
QBCore:Notify
Custom Notify Bridge

อย่าแก้ Shop Logic ทั้งระบบถ้าธุรกรรมทำงานถูกแล้ว

51. Script มี Error หลังเปลี่ยน QBCore Version

ถ้า Resource ใช้ได้ก่อน Update qb-core แต่พังหลัง Update

ตรวจ

QBCore API
Exports
Events
Shared Data
PlayerData Structure
Dependencies

จากนั้นเปรียบเทียบ Changelog/Version

ไม่ควร Downgrade Core Production ทันทีโดยไม่ Backup

ควรทดสอบบน Test Serverก่อน

52. Script พังหลัง Update ตัวมันเอง

ถ้า Core ไม่เปลี่ยน แต่ Script ถูก Update

ตรวจ

New Config
New Dependency
New SQL
Inventory Requirement
Target Requirement
Framework Bridge

ปัญหาที่พบบ่อยคือ Copy

config.lua

รุ่นเก่าทับ Version ใหม่ทั้งหมด

ทำให้ Config ใหม่บางค่าไม่มี

53. อย่า Copy Config เก่าทับโดยไม่ Merge

สมมติ

v1 Config = 30 Options
v2 Config = 45 Options

ถ้า Copy v1 ทับ v2

15 Options ใหม่จะหาย

จากนั้น Script อาจขึ้น

attempt to index nil

หรือใช้ Default ไม่ได้

วิธีที่ถูกคือ

เปิด Config ใหม่
↓
นำ Custom Values เก่ามา Merge

ไม่ใช่ Replace ทั้งไฟล์

54. Resource Folder ซ้อน

หลังแตก ZIP อาจเป็น

resources/
└── my-script/
    └── my-script/
        ├── fxmanifest.lua
        └── client.lua

ซึ่งผิดตำแหน่ง

ควรเป็น

resources/
└── my-script/
    ├── fxmanifest.lua
    └── client.lua

นี่เป็นปัญหาพื้นฐานแต่พบได้บ่อยมาก

55. Rename Resource ทำให้ Export/Dependency พัง

ตัวอย่างเดิม

qb-phone

ถูก Rename เป็น

phone

แต่ Script อื่นเรียก

exports['qb-phone']

ก็จะพัง

ก่อน Rename Resource ต้อง Search ทั้ง Server ว่ามี

exports
dependencies
@resource/file
events/config

อ้างชื่อเดิมหรือไม่

56. QBCore Script เก่าควรดูอะไร

ตรวจ

วันที่ Update
qb-core Version
fxmanifest
Inventory API
Target API
Database Wrapper
Callbacks
Events

ถ้า Script ไม่ Update มาหลายปีและต้อง Patch หลายจุด การหา Resource ใหม่ที่รองรับ Current QBCore อาจคุ้มกว่า

โดยเฉพาะระบบสำคัญอย่าง

Inventory
Phone
Housing
Garage
Police

57. lua54 'yes' ช่วยแก้ทุก Error หรือไม่

ไม่

แม้ Current qb-core Manifest ยังมี Directive นี้อยู่ แต่ FiveM ปัจจุบันใช้ Lua 5.4 แล้ว

การเพิ่ม

lua54 'yes'

ไปทุก Script ไม่ใช่วิธีแก้

nil
missing export
database
dependency

ให้อ่าน Error ตามจริง

58. ล้าง Cache ช่วยไหม

ไม่ใช่วิธีแรกสำหรับ Error อย่าง

Player nil
No such export
Missing dependency
Unknown column
Callback ไม่ตอบ

ปัญหาเหล่านี้เป็น Architecture/Code/Database

ล้าง Cache ใช้เมื่อมีเหตุผลชัดว่าปัญหาเกิดจาก Client Resource Cache

อย่าใช้เป็น Universal Fix

59. วิธีแยกว่า Core หรือ Script เสีย

ตรวจ Base QBCore Features

ถ้า

Character ใช้ได้
PlayerData โหลด
Money ใช้ได้
Job ใช้ได้
Inventory Base ใช้ได้

แต่ Custom Mechanic Script พัง

ให้โฟกัสที่ Mechanic Script

แต่ถ้า

Character
Money
Jobs
หลาย qb-* Resources

พังพร้อมกัน

ให้ย้อนกลับมาตรวจ

qb-core
oxmysql
Database

ก่อน

60. วิธี Debug QBCore Script ที่เร็วที่สุด

ทำตามลำดับนี้

① อ่าน Error แรกใน Server Console

② เปิด F8 ดู Client Error

③ ตรวจ oxmysql

④ ตรวจ qb-core

⑤ ตรวจ Start Order

⑥ เปิด fxmanifest.lua

⑦ ตรวจ GetCoreObject

⑧ ตรวจ Player Object / PlayerData

⑨ ตรวจ Job / Item Definitions

⑩ ตรวจ Callback / Event

⑪ ตรวจ Inventory / Target

⑫ ตรวจ SQL

⑬ ตรวจ Version

⑭ ทดสอบใหม่

อย่าแก้ 10 จุดพร้อมกัน

แก้ทีละ Root Cause แล้วทดสอบใหม่ทุกครั้ง

ตารางอาการ QBCore Script กับสาเหตุที่ควรตรวจ

อาการตรวจอันดับแรก
QBCore = nilGetCoreObject / qb-core
No such export GetCoreObjectCore/Resource Name/Version
Player = nilPlayer Loading / source
PlayerData = nilOnPlayerLoaded / Timing
Job ไม่อัปเดตOnJobUpdate / Cached PlayerData
Callback ไม่ตอบCreateCallback / Server Error
Item ไม่เข้าInventory / Item Name
Target ไม่ขึ้นTarget Resource / Config
Menu ไม่เปิดF8 / NUI / Client Error
Money ไม่เข้าPlayer Object / Money Type
Table ไม่มีSQL Installation
Unknown ColumnSQL Migration
ใช้ได้หลัง RestartStart Order
หลาย QB Scripts พังCore / Database
Script เดียวพังVersion / Integration

Checklist QBCore Script ไม่ทำงาน

Core

  • oxmysql Start

  • Database Connected

  • qb-core Start

  • ไม่มี Critical Core Error

Player

  • Character Load

  • Player Object มี

  • PlayerData มี

  • Citizen ID มี

  • Job โหลด

  • Money โหลด

Resource

  • Folder ไม่ซ้อน

  • fxmanifest.lua ถูก

  • Client/Server Files ครบ

  • Dependencies ครบ

  • Resource Name ถูก

QBCore

  • GetCoreObject() ทำงาน

  • Callback Name ถูก

  • Event Name ถูก

  • Job/Item/Gang มีใน Shared Data

  • PlayerData Update ถูก Handle

Integration

  • Inventory ถูกระบบ

  • Target ถูกระบบ

  • ox_lib มีหากต้องใช้

  • Phone/Voice/Notification Bridge ถูก

Database

  • Tables ครบ

  • Columns ครบ

  • SQL Version ตรง

  • Migration ทำแล้ว

  • ไม่มี Duplicate Migration

Debug

  • อ่าน Error แรก

  • ตรวจ F8

  • ตรวจ Server Console

  • ใช้ print() ไล่ Flow

  • ทดสอบทีละจุด

ตัวอย่าง Debug Flow ที่ใช้ได้จริง

สมมติ Player กดซื้อสินค้าแต่ไม่มีอะไรเกิดขึ้น

เริ่ม Client

print('shop: button pressed')

TriggerServerEvent('myshop:server:buy', 'water')

Server

RegisterNetEvent('myshop:server:buy', function(item)
    print('shop: event received')

    local src = source
    local Player = QBCore.Functions.GetPlayer(src)

    if not Player then
        print('shop: player not found')
        return
    end

    print('shop: player found')
end)

จากนั้นดู Flow

button pressed มี?
↓
ถ้าไม่มี → Client/UI

event received มี?
↓
ถ้าไม่มี → Event

player found มี?
↓
ถ้าไม่มี → Player/Core

ถึงตรงนี้แล้ว?
↓
ตรวจ Money/Inventory ต่อ

นี่มีประสิทธิภาพกว่าการเดา

Paid QBCore Script ไม่ทำงานควรทำอย่างไร

ถ้าเป็น Asset Escrow Script ที่แก้ Core ไม่ได้ ให้รวบรวม

Script Version
QBCore Version
Inventory
Target
ox_lib Version
Error เต็ม
F8
Server Console
ขั้นตอนที่ทำให้ Error เกิด

แล้วตรวจไฟล์ที่ Developer เปิดให้แก้ เช่น

config
bridge
custom
locales

หาก Error อยู่ Protected Core ให้ส่งข้อมูลให้ Developer

อย่าพยายาม Bypass Escrow

อย่าเปลี่ยน Framework เพื่อแก้ Script ตัวเดียว

ถ้า Base QBCore ใช้งานดีและ Custom Script ตัวเดียว Error

การย้าย

QBCore
→ Qbox

หรือ

QBCore
→ ESX

เพื่อแก้ Script เดียวมักสร้างงานมากกว่าเดิม

ควรแก้

Compatibility
Dependency
Bridge
Version

ของ Resource นั้นก่อน

Framework Migration ควรเกิดจาก Architecture Decision ไม่ใช่ Error รายตัว

สรุป QBCore Script ไม่ทำงาน แก้อย่างไร

ถ้า QBCore Script ไม่ทำงาน ให้เริ่มจากโครงสร้างพื้นฐาน

Database
↓
oxmysql
↓
qb-core
↓
Player Loading
↓
Custom Script
↓
Inventory / Target

Current QBCore ใช้

local QBCore = exports['qb-core']:GetCoreObject()

เป็นวิธีมาตรฐานในการดึง Core Object และปัจจุบันยังสามารถเลือกเฉพาะส่วนอย่าง Functions หรือ Shared ได้

สำหรับ Player Logic ฝั่ง Server ควรตรวจ Player ทุกครั้ง

local Player = QBCore.Functions.GetPlayer(source)

if not Player then
    return
end

ส่วน Client Scripts ที่ต้องใช้ PlayerData ตั้งแต่หลัง Character Selection ควรคำนึงถึง Event อย่าง

QBCore:Client:OnPlayerLoaded
QBCore:Player:SetPlayerData
QBCore:Client:OnJobUpdate

เพื่อไม่ใช้ข้อมูลเก่าหรืออ่าน PlayerData ก่อนพร้อม

ถ้า Item หรือ Stash ไม่ทำงาน ให้ตรวจ Inventory Integration และถ้า Interaction ไม่ขึ้นให้ตรวจ Target แยกจาก Framework เพราะ

QBCore Compatible

ไม่ได้หมายความว่า Script จะรองรับ Inventory และ Target ทุกตัวโดยอัตโนมัติ

แนวทางของ comsiam คือเมื่อเจอ QBCore Script Error ให้หา Layer ที่เสียก่อน แล้วแก้ Error แรกจาก Console/F8 ทีละจุด วิธีนี้เร็วกว่าการ Clear Cache หรือ Reinstall Framework โดยไม่มีหลักฐาน

สำหรับ Production Server comsiam แนะนำให้มี Clean QBCore Base และ Test Server แยกไว้เสมอ เพราะถ้า Custom Script ใหม่มีปัญหา คุณสามารถนำไปทดสอบบน Base ที่รู้ว่า oxmysql, qb-core, PlayerData และ Inventory ทำงานอยู่แล้ว และแยกได้ทันทีว่าปัญหาอยู่ Core หรือ Resource ใหม่

Comments

Popular posts from this blog

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

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

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