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 = nil | GetCoreObject / qb-core |
No such export GetCoreObject | Core/Resource Name/Version |
| Player = nil | Player Loading / source |
| PlayerData = nil | OnPlayerLoaded / 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 Column | SQL Migration |
| ใช้ได้หลัง Restart | Start Order |
| หลาย QB Scripts พัง | Core / Database |
| Script เดียวพัง | Version / Integration |
Checklist QBCore Script ไม่ทำงาน
Core
oxmysqlStartDatabase Connected
qb-coreStartไม่มี 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
Post a Comment