FiveM OneSync Infinity คืออะไร? ระบบรองรับผู้เล่นจำนวนมากของ FiveM ทำงานอย่างไร
FiveM OneSync Infinity คือสถาปัตยกรรมของ OneSync ที่ออกแบบให้ FiveM สามารถรองรับผู้เล่นจำนวนมากขึ้น โดยใช้ระบบ Player/Entity Culling, Focus Zone และการขยาย Object ID Space เพื่อไม่ให้ Client ต้องสร้างและ Synchronize ผู้เล่นกับ Entity ทุกตัวบน Server พร้อมกัน
เอกสาร Cfx.re ปัจจุบันระบุว่า OneSync: Infinity รองรับสถาปัตยกรรมได้สูงสุดประมาณ
2048 Players
โดยมีการเปลี่ยนแปลงสำคัญ เช่น
Object ID Space
8192
↓
65535
และใช้
Player / Ped / Vehicle Culling
+
Focus Zone
เพื่อจำกัดว่า Client แต่ละคนต้องรับรู้ Entity ใดบ้าง
แนวคิดสำคัญที่สุดคือ
Server มีผู้เล่นจำนวนมาก
↓
Client ไม่จำเป็นต้องเห็นทุกคน
↓
OneSync เลือกเฉพาะสิ่งที่อยู่ใน Scope
↓
Client สร้างเฉพาะ Entity ที่เกี่ยวข้อง
นี่ทำให้ FiveM Server สามารถ Scale จำนวน Player ได้มากขึ้นโดยไม่บังคับให้ Client แต่ละเครื่องจำลองผู้เล่นทั้งหมดบน Serverพร้อมกัน
① OneSync Infinity คืออะไร
OneSync Infinity เป็นส่วนหนึ่งของระบบ Synchronization ของ FiveM ที่เน้นการ Scale Server ให้รองรับ Player จำนวนมาก
ระบบใช้แนวคิดสำคัญ เช่น
Extended Object IDs
Player Culling
Entity Culling
Focus Zone
Server-side State Awareness
เมื่อรวมกันแล้ว Client แต่ละคนจะรับเฉพาะ Game State ที่จำเป็นต่อพื้นที่รอบตัวเอง
② Infinity ต่างจากการเพิ่ม sv_maxclients อย่างเดียวอย่างไร
การเพิ่ม
sv_maxclients 128
ไม่ได้แก้ปัญหาว่า Client จะต้องจัดการ Player และ Entity จำนวนมากอย่างไร
Infinity แก้ที่ Synchronization Architecture
เช่นแทนที่จะให้ Client มี
Player ทั้ง Server
ระบบให้ Clientมีเฉพาะ
Player ที่อยู่ใน Focus Zone
จึงสามารถ Scale ได้ดีกว่า
③ OneSync Infinity รองรับกี่คน
เอกสาร Cfx.re ปัจจุบันระบุ Architecture รองรับได้สูงสุดถึง
2048 Players
และระบุว่ามี Server ที่รองรับ Concurrent Players ระดับมากกว่า 1,000 คน
แต่ตัวเลขนี้ไม่ควรถูกตีความว่า Server ทุกเครื่องสามารถเปิด 2,048 Slots แล้วทำงานได้ดีทันที
ยังขึ้นกับ
Hardware
Network
Resources
Database
Script Performance
Entity Density
Subscription/Server Slot Entitlement
④ 2048 Players ไม่ได้แปลว่า Client เห็น 2048 คน
นี่คือจุดสำคัญที่สุด
Client หนึ่งไม่จำเป็นต้องสร้าง Player Peds ของ Player ทั้ง 2,048 คน
Infinity ใช้ Culling
2,048 Players บน Server
↓
Client A
↓
เห็นเฉพาะ Players รอบตัว
จึงต่างจากการพยายามจำลองผู้เล่นทั้งหมดบน Client เดียว
⑤ Object ID Space คืออะไร
Networked Entities ต้องมี Object IDs สำหรับระบบ Network
OneSync Infinity ขยาย Object ID Space จากเดิม
8192
หรือ
1 << 13
ไปเป็น
65535
หรือ
(1 << 16) - 1
ช่วยเพิ่มจำนวน Network Objects ที่ระบบสามารถระบุได้
⑥ ทำไมต้องขยายจาก 8192 เป็น 65535
Server ที่มีผู้เล่นจำนวนมากมี
Player Peds
Vehicles
NPCs
Objects
Mission Entities
จำนวนมากขึ้น
Object ID Space เดิมจึงเป็นข้อจำกัดสำคัญ
การขยายเป็น 16-bit Space ทำให้ระบบมีพื้นที่สำหรับ Network Object IDs มากขึ้น
แต่ไม่ได้หมายความว่าควร Spawn 65,535 Entities ในบริเวณเดียวกัน
⑦ 65535 คือจำนวน Entity ที่ Client รับได้พร้อมกันไหม
ไม่ควรตีความแบบนั้น
65535 ที่เอกสารพูดถึงคือ Object ID Space
ไม่ใช่คำรับประกันว่า
Client หนึ่ง
สามารถ Stream
65,535 Entities
ในระยะเดียวกัน
Game Engine และ Streaming System ยังมีข้อจำกัด
Entity Density สูงเกินไปยังทำให้ Client มีปัญหาได้
⑧ Culling คืออะไร
Culling คือการไม่ส่งหรือไม่สร้าง Entity บน Client เมื่อ Entity นั้นอยู่นอกพื้นที่ที่ Client จำเป็นต้องรู้
Concept
อยู่ใกล้
→ Sync
อยู่ไกล
→ Cull
ช่วยลด
Bandwidth
Client CPU
Memory Usage
Entity Processing
Network Traffic
⑨ Focus Zone คืออะไร
Focus Zone คือพื้นที่รอบ Player ที่ใช้กำหนดว่า Entity/Player ใดควรถูกสร้างและ Synchronize บน Client
เอกสาร OneSync ปัจจุบันระบุค่า Focus Zone ที่ Hardcoded อยู่ประมาณ
424 Units
รอบ Player
จึงเกิด Concept
Player
↓
Focus Zone ~424 units
↓
Relevant Entities
⑩ 424 Units เป็นเมตรไหม
ไม่ควรตีความตรง ๆ ว่าเป็นหน่วยเมตรจริงแบบ Physical Measurement
เอกสารใช้คำว่า Game Units
สำหรับ Script Logic ไม่ควร Hardcode Security หรือ Gameplay ทุกอย่างจากค่า 424 เพียงเพราะเป็น Default Culling Radius
ใช้ Distance ที่เหมาะกับ Use Case ของระบบตัวเอง
⑪ Player Culling คืออะไร
Infinity ไม่สร้าง Local Player Representation ของ Player ที่อยู่นอก Focus Zone โดยไม่จำเป็น
ดังนั้น
Server:
มี Player 500 คน
Client:
อาจเห็น Local Players เพียงจำนวนหนึ่ง
นี่มีผลต่อการเขียน Client Script อย่างมาก
⑫ Player Ped Culling คืออะไร
Player Ped ของผู้เล่นที่อยู่นอก Scope ไม่จำเป็นต้องถูกสร้างบน Client
ดังนั้น Script ฝั่ง Client ไม่ควรสมมติว่า
Player บน Server
=
ต้องมี Ped อยู่บน Client นี้
เสมอไป
นี่เป็นหนึ่งในความแตกต่างสำคัญของ Infinity Architecture
⑬ Vehicle Culling คืออะไร
Vehicle ที่อยู่นอกพื้นที่เกี่ยวข้องกับ Client ก็สามารถถูก Cull ตาม Synchronization Rules
ตัวอย่าง
Vehicle อยู่ไกลมาก
↓
Client ไม่จำเป็นต้องมี Vehicle Entity
ช่วยลดจำนวน Network Entities ที่ Client ต้องจัดการ
⑭ Scope คืออะไร
Scope หมายถึงชุด Players/Entities ที่ Client ปัจจุบันรับรู้ผ่าน Network
ตัวอย่าง
Player B เข้าใกล้ Player A
↓
B เข้า Scope ของ A
เมื่อออกไกล
B ออกจาก Scope
Local Representation จึงสามารถถูกสร้างหรือลบตามระบบ
⑮ Client เห็น Player ทุกคนไหม
ไม่
นี่คือสิ่งที่ FiveM Developer ต้องเปลี่ยนวิธีคิด
อย่าสมมติว่า
GetActivePlayers()
จะให้ Player ทุกคนที่ Connected อยู่บน Server
ใน OneSync Infinity Client รู้จัก Local Players ที่อยู่ใน Scope/Context เท่านั้น
⑯ GetActivePlayers ใช้ไม่ได้แล้วหรือไม่
ยังใช้ได้สำหรับ Local Players ที่ Client รู้จัก
แต่ไม่ควรใช้เพื่อถาม
ตอนนี้ Server มี Player ทุกคนใครบ้าง?
ถ้าต้องการ Global Player List ควรทำฝั่ง Server
⑰ Loop Player ทั้ง Server ควรทำที่ไหน
ถ้าต้อง Iterate Player Connected ทั้ง Server ให้ทำ Server-side
ตัวอย่าง
local players =
GetPlayers()
for _, playerId in ipairs(
players
) do
print(playerId)
end
จากนั้นค่อยส่งเฉพาะข้อมูลที่ Client จำเป็นต้องรู้
⑱ ทำไม Global Player Logic ต้องอยู่ Server
เพราะ Server รู้ Connections ทั้งหมด
ส่วน Client ถูกออกแบบให้รับรู้เฉพาะ Relevant Players
จึงควรเป็น
Global Player Logic
→ Server
ส่วน
Nearby Player Rendering
→ Client
นี่เป็น Architecture ที่เหมาะกับ Infinity มากกว่า
⑲ ตัวอย่าง Script ที่มีปัญหากับ Infinity
สมมติ Client ทำ
for _, player in ipairs(
GetActivePlayers()
) do
-- คิดว่านี่คือทุกคนใน Server
end
จากนั้นใช้ List นี้สร้าง Scoreboard
Scoreboard อาจไม่ครบ
เพราะ Players นอก Scope ไม่ได้มี Local Player Representation
⑳ Scoreboard ควรทำอย่างไร
ให้ Server เป็นผู้สร้าง Player List
Client
↓
ขอ Scoreboard
↓
Server
↓
Get Players
↓
เลือกข้อมูลที่อนุญาต
↓
ส่ง Client
↓
NUI Display
อย่าสร้าง Global Scoreboard จาก GetActivePlayers() อย่างเดียว
㉑ Admin Player List ก็เช่นเดียวกัน
Admin Menu ที่ต้องเห็นทุกคนควรใช้ข้อมูล Server-side
เช่น
Server ID
Name
Job
Ping
Permission
ตามข้อมูลที่ Server มีสิทธิ์เปิดเผย
Client Scope ไม่ควรเป็น Source of Truth สำหรับ Global Admin List
㉒ Player ID กับ Server ID ต้องแยกกัน
Client Player Index เป็น Local
Server ID ใช้อ้าง Player Connection ฝั่ง Server
ตัวอย่าง Client
local serverId =
GetPlayerServerId(
player
)
แต่ Player ที่อยู่นอก Scope อาจไม่มี Local Player Index ให้ Client นั้น
ดังนั้น Server ID เหมาะกับ Global Server Logic มากกว่า
㉓ Entity Handle กับ Infinity
Entity Handle ยังเป็น Local Reference
ตัวอย่างรถคันเดียว
Client A
Handle 100
Client B
Handle 450
ถ้ารถอยู่ใน Scope ของทั้งสอง
แต่เมื่อออก Scope Client A อาจไม่มี Local Handle ของรถนั้นอีก
จึงต้องออกแบบ Entity Lifecycle อย่างระมัดระวัง
㉔ Network ID ยังสำคัญไหม
สำคัญมาก
Network ID ใช้อ้าง Networked Entity ข้าม Machines ในช่วง Lifetime ของ Entity
Concept
Entity
↓
Network ID
↓
OneSync Infinity
↓
Relevant Clients
แต่ Net ID ไม่รับประกันว่า Client ทุกคนมี Local Entity นั้นอยู่
㉕ มี Net ID แล้ว NetToVeh ได้เสมอไหม
ไม่
ถ้า Vehicle อยู่นอก Scope
Client อาจไม่มี Local Vehicle Entity
ควรตรวจ
NetworkDoesEntityExistWithNetworkId(
netId
)
ก่อน Resolve
ตาม Use Case
㉖ ตัวอย่างรอ Entity เข้า Scope
local timeout =
GetGameTimer() + 5000
while not NetworkDoesEntityExistWithNetworkId(
netId
) do
if GetGameTimer() >
timeout then
return
end
Wait(0)
end
local vehicle =
NetToVeh(netId)
if not DoesEntityExist(vehicle) then
return
end
อย่ารอแบบ Infinite Loop โดยไม่มี Timeout
㉗ Entity ออกจาก Scope แล้ว Handle เดิมใช้ต่อได้ไหม
ไม่ควรถือว่า Valid
หากเก็บ
local missionVehicle =
vehicle
ไว้นาน
ก่อนใช้ควรตรวจ
if not DoesEntityExist(
missionVehicle
) then
return
end
เพราะ Local Entity สามารถถูก Cull/Recreated ได้ตาม Network Lifecycle
㉘ Ownership เกี่ยวกับ Infinity อย่างไร
เมื่อ Entity ออกจาก Scope ของ Owner เดิม
Ownership สามารถ
Migrate
หรือ
Disown
ได้
Cfx.re ระบุว่า Faraway Entities จะไม่ถูกควบคุมโดย Original Owner ต่อไปเสมอ
ช่วยลดปัญหา Entity ถูกผูกกับ Client ที่อยู่ไกล
㉙ Client ที่ Spawn รถเป็น Owner ตลอดไหม
ไม่
Infinity ยิ่งทำให้สมมติฐานนี้อันตราย
Client A Spawn Vehicle
↓
A Own
↓
A ออกไกล
↓
Entity Cull/Migrate
↓
Owner อาจเปลี่ยน
จึงไม่ควรออกแบบ Mission Logic โดยผูกกับ Client A ตลอด Lifetime
㉚ Network ID เปลี่ยนเมื่อ Owner เปลี่ยนไหม
สำหรับ Lifetime ของ Network Entity เดิม Network ID จะยังใช้อ้าง Entity เดิม
Ownership เปลี่ยนได้โดยไม่จำเป็นต้องเปลี่ยน Network ID
นี่ทำให้ Net ID เหมาะกับ Runtime Entity References มากกว่า Local Handle
㉛ OneSync Infinity กับ Server-created Entity
Server-created Entities มีประโยชน์มากใน Infinity Architecture
เช่น Server สร้าง Mission Vehicle
local vehicle =
CreateVehicleServerSetter(
joaat('sultan'),
'automobile',
x,
y,
z,
heading
)
จากนั้น OneSync จัด Network Lifecycle ให้ Relevant Clients
㉜ ทำไม Server-created Entity เหมาะกับ Server ใหญ่
เพราะช่วยลดการให้ Client เป็นผู้ Author Entity Creation
Flow
Client ขอ Mission
↓
Server Validate
↓
Server Create Entity
↓
OneSync Sync เฉพาะ Relevant Clients
เหมาะกับ Server-authoritative Architecture มากกว่า Client Spawn ทุกอย่างเอง
㉝ Server-created Entity ต้องมี Player อยู่ใกล้ไหม
ต้องแยก API
Server-side RPC Entity Creation บางแบบอาจต้องมี Client ใกล้เพื่อ Execute และสามารถ Fail ได้
Cfx.re Migration Docs จึงแนะนำให้เข้าใจความต่างระหว่าง
Server RPC creation
กับ
Server Setter
และตรวจ Failure เสมอ
㉞ CreateVehicleServerSetter น่าสนใจอย่างไร
CreateVehicleServerSetter() เป็น Server Setter ที่ Cfx.re ใช้ใน OneSync Examples
ช่วย Register/Create Vehicle จาก Server-side State โดยตรงมากกว่า RPC-style Creation ในหลาย Use Cases
ตัวอย่าง
local vehicle =
CreateVehicleServerSetter(
joaat('blista'),
'automobile',
x,
y,
z,
heading
)
จากนั้นตรวจ
if vehicle == 0 then
return
end
㉟ Orphaned Entity คืออะไร
Server-created Entity อาจยังไม่มี Client Owner เมื่อไม่มี Player อยู่ใน Scope
Concept
Server Entity
↓
ไม่มี Client ใกล้
↓
Orphaned
เมื่อ Player เข้ามาในพื้นที่จึงสามารถเกิด Client Simulation Ownership ได้
㊱ SetEntityOrphanMode เกี่ยวข้องอย่างไร
Server สามารถกำหนด
SetEntityOrphanMode(
entity,
2
)
เพื่อใช้ KeepEntity Mode สำหรับ Runtime Entity ที่ต้องการให้ Server ไม่ Cleanup เพียงเพราะไม่มี Client Owner
เหมาะกับ Server-created Mission/Persistent-runtime Entity บางประเภท
㊲ KeepEntity อยู่หลัง Restart ไหม
ไม่
Infinity Runtime Persistence ไม่ใช่ Database Persistence
ถ้าต้องการรถคงอยู่หลัง Server Restart ต้องเก็บ
Database ID
Model
Properties
Coords
Owner
แล้ว Spawn Entity ใหม่เมื่อ Serverกลับมา
㊳ Infinity กับ State Bags
State Bags ทำงานได้ดีมากกับ Scoped Entity Architecture
ตัวอย่าง Server Set
Entity(vehicle).state:set(
'fuel',
80,
true
)
เมื่อ Entityถูก Replicate ไป Relevant Client State ที่เกี่ยวข้องสามารถเดินทางตาม Replication Policy
ช่วยลดการ Broadcast Custom Events ไปทุกคน
㊴ ทำไม State Bags เหมาะกับ Infinity
เพราะ State สามารถผูกกับ
Player
Entity
Global State
และ Relevant Clients รับตาม State Awareness
ไม่จำเป็นต้องทำ
TriggerClientEvent(
'vehicle:update',
-1,
netId,
state
)
ทุกครั้งสำหรับ Entity ที่มีเพียง Player ใกล้ ๆ เท่านั้นที่ต้องใช้
㊵ playerEnteredScope ควรใช้ไหม
ใช้ได้ แต่ Cfx.re มี Performance Warning ชัดเจน
เพราะเมื่อ Players จำนวนมากอยู่ใน Scope Events จะถูกเรียกเพิ่มตาม Pair ของ Players ที่เข้า/ออก Scope
ตัวอย่างมี 32 Players รอบ Player หนึ่ง
ระบบอาจมี Scope Event Calls จำนวนมาก
จึงไม่เหมาะสำหรับ State Synchronization ทั่วไป
㊶ Cfx.re แนะนำอะไรแทน Scope Events
ถ้า Use Case เป็น State
Cfx.re แนะนำพิจารณา
State Bags
+
AddStateBagChangeHandler
แทน playerEnteredScope / playerLeftScope
เพราะ Scale ได้เหมาะกับ Scoped State มากกว่าในหลายกรณี
㊷ OneSync Infinity กับ Routing Bucket
Routing Bucket ยังทำงานร่วมกับ Infinity
ตัวอย่าง
Bucket 0
→ Main World
Bucket 100
→ Party A
Bucket 200
→ Party B
ภายในแต่ละ Bucket ยังมี Scope/Culling ตามระบบ OneSync
ดังนั้น Instance และ Culling ทำงานคนละ Layer แต่ใช้ร่วมกันได้
㊸ Routing Bucket ทำให้ Client เห็นทุกคนใน Bucket ไหม
ไม่ควรสมมติแบบนั้น
แม้อยู่ Bucket เดียวกัน หาก Player อยู่ไกลกันมาก Scope/Culling ยังสามารถมีผล
Routing Bucket กำหนด Routing Context
ส่วน Focus Zone กำหนด Relevant Local Scope
จึงเป็น
Bucket
+
Scope
ไม่ใช่ Bucket อย่างเดียว
㊹ Infinity กับ Entity Lockdown
Server สามารถใช้ Routing Bucket Entity Lockdown
SetRoutingBucketEntityLockdownMode(
bucket,
'strict'
)
เพื่อห้าม Clients สร้าง Entity ใน Bucket
เหมาะกับ Server ใหญ่ที่ต้องการลด Client-authored Entities
㊺ Infinity เป็น Anti-Cheat ไหม
ไม่
Infinity เป็น Synchronization Architecture
แม้
Culling
Server-created Entity
Entity Lockdown
State Awareness
จะช่วยให้ Server ออกแบบ Security ได้ดีขึ้น
แต่ Network Events ยังต้อง Validate
㊻ Secure Event ยังต้องทำเหมือนเดิมไหม
ต้องทำ
ตัวอย่าง Client
TriggerServerEvent(
'job:complete'
)
Server ยังต้องตรวจ
Player
Position
Mission State
Permission
Inventory
Reward
OneSync ช่วยให้ Server ตรวจ Entity/Position ได้ดีขึ้น
แต่ไม่ได้ Validate Business Logic ให้อัตโนมัติ
㊼ Infinity ช่วย Server Position Validation อย่างไร
Serverสามารถ
local ped =
GetPlayerPed(source)
local coords =
GetEntityCoords(ped)
แล้วตรวจ Distance จาก Mission Point
แทนให้ Clientส่ง Coordinates แล้วเชื่อ
นี่เป็นประโยชน์สำคัญของ State Awareness
㊽ Infinity กับ ESX ใช้ได้ไหม
ได้
ESX จัดการ Framework Layer เช่น
Job
Money
Inventory
Player Data
Infinity จัดการ
Player/Entity Networking
Scope
Ownership
State Awareness
ใช้ร่วมกันได้
㊾ Infinity กับ QBCore/Qbox
หลักเดียวกัน
ไม่ว่า Framework จะเป็น
ESX
QBCore
Qbox
Standalone
Core Multiplayer Networking ยังใช้ OneSync Concepts
ดังนั้น Script ที่เข้าใจ Infinity จะย้าย Framework ได้ง่ายกว่า
㊿ OneSync Infinity ทำให้ FPS ดีขึ้นไหม
เอกสาร Cfx.re ระบุว่า Infinity มี Performance ที่ดีกว่า Plain OneSync ในบางส่วนเนื่องจาก Player Ped Culling
แต่ไม่ได้หมายความว่า
เปิด Infinity
→ FPS สูงทันทีทุก Server
ถ้า Resource ยังทำ
Draw ทุกอย่างทุก Frame
Spawn Entity จำนวนมหาศาล
Send NUI ทุก Tick
Broadcast Events ตลอด
Heavy Client Loops
FPS ก็ยังต่ำได้
51 Infinity ทำให้ Server CPU เบาลงเสมอไหม
ไม่ควรรับประกันแบบนั้น
Culling ช่วยลด Unnecessary Synchronization
แต่ Server ที่มี Player มากขึ้นก็มี
Events มากขึ้น
Database Queries มากขึ้น
Framework Work มากขึ้น
Voice Traffic มากขึ้น
Entity State มากขึ้น
Resource Architecture ยังเป็นตัวกำหนด Performance อย่างมาก
52 Entity เยอะในพื้นที่เดียวกันยังเป็นปัญหาไหม
เป็น
เอกสาร Migration เตือนว่า หากมี Entities ใน Range มากกว่าที่ Game รองรับ Clients ในพื้นที่สามารถเกิดปัญหาหรือ Timeout
ดังนั้น
Infinity
≠
Unlimited local entities
อย่าสร้างรถหรือ NPC หลายพันตัวในจุดเดียวแล้วคาดว่า Culling จะแก้ทั้งหมด
53 Server 1000 คนควรอยู่จุดเดียวกันไหม
ในทางเทคนิค Player Density สูงมากยังสร้างภาระมหาศาลกับ
Client Rendering
Networking
Voice
Physics
Player Peds
UI
Infinity เหมาะกับ Server ที่ Player กระจายตัวและใช้ Culling ได้อย่างมีประสิทธิภาพ
ไม่ได้ทำให้ Crowd Size ไร้ข้อจำกัด
54 Voice Chat เกี่ยวกับ Infinity ไหม
ใน Server ผู้เล่นจำนวนมาก Voice Architecture ก็สำคัญ
แม้ OneSync ช่วย Networking ของ Game State แต่ Voice Resource ยังต้องจัด Proximity, Channels และ Routing อย่างเหมาะสม
อย่า Broadcast Voice/Data ไป Player ทุกคนโดยไม่มีเหตุผล
55 Client Script สำหรับ Infinity ควรออกแบบอย่างไร
หลักสำคัญคือ
อย่าสมมติว่า Client เห็นทุก Player
อย่าสมมติว่า Entity อยู่ตลอด
อย่าเก็บ Handle แบบถาวร
อย่า Broadcast ทุก State
อย่า Iterate Global Players ฝั่ง Client
และ
Global Logic → Server
Nearby Logic → Client
State → State Bags เมื่อเหมาะสม
Entity Reference → Network ID
56 Server Script สำหรับ Infinity ควรออกแบบอย่างไร
Server ควรเป็น Authority ของ
Player Lists
Mission State
Economy
Inventory
Permissions
Global Match State
และใช้ OneSync State Awareness สำหรับ
Player Position
Entity Validation
Routing Buckets
State Bags
Server-created Entities
ตาม Use Case
57 ต้องตั้งค่า Infinity แยกจาก OneSync ไหม
ในเอกสารตั้งค่า FXServer ปัจจุบัน การเปิด OneSync ใช้
set onesync on
และเอกสาร OneSync อธิบาย Infinity เป็น Architecture/Mode ของระบบ OneSync ปัจจุบัน
สำหรับ Server ใหม่ไม่ควร Copy Configuration เก่าจากบทความหลายปีก่อนแล้วเปิด ConVars แบบสุ่ม
ใช้ Configuration และ Server Artifact ปัจจุบันเป็นหลัก
58 Resource ระบุว่าต้องใช้ OneSync ได้ไหม
ได้ใน fxmanifest.lua
dependencies {
'/onesync'
}
/onesync เป็น Runtime Constraint ที่หมายถึง Resource ต้องการ State Awareness ไม่ถูก Disable
เหมาะกับ Resource ที่ใช้
Server Entity Natives
State Bags
Routing Buckets
อย่างจริงจัง
59 Checklist ทำ Script ให้รองรับ OneSync Infinity
ตรวจอย่างน้อย
① Client สมมติว่าเห็น Player ทุกคนหรือไม่?
② Global Player List อยู่ Server หรือยัง?
③ GetActivePlayers ถูกใช้ผิดวัตถุประสงค์หรือไม่?
④ Entity Handle ถูกเก็บนานเกินไปหรือไม่?
⑤ ก่อนใช้ Handle ตรวจ DoesEntityExist หรือยัง?
⑥ ข้าม Client ใช้ Network ID หรือยัง?
⑦ ตรวจ Entity อยู่ใน Scope หรือยัง?
⑧ มี Infinite Wait รอ Entity หรือไม่?
⑨ Timeout ถูกใส่หรือยัง?
⑩ Ownership สามารถ Migration ได้หรือไม่?
⑪ Logic ผูกกับ Original Owner หรือไม่?
⑫ Server-created Entity เหมาะกว่าหรือไม่?
⑬ RPC Native Failure ถูก Handle หรือยัง?
⑭ State ใช้ State Bag ได้หรือไม่?
⑮ ใช้ playerEnteredScope มากเกินไปหรือไม่?
⑯ Routing Bucket ถูกออกแบบถูกหรือไม่?
⑰ Entity Lockdown เหมาะกับระบบหรือไม่?
⑱ Security Event Validate Server-side หรือไม่?
⑲ Player Position ตรวจ Server-side หรือไม่?
⑳ Spawn Entities หนาแน่นเกินไปหรือไม่?
㉑ Broadcast Event ไปทุกคนโดยไม่จำเป็นหรือไม่?
㉒ Resource Threads Scale ตาม Player Count หรือไม่?
㉓ Database Queries Scale ได้หรือไม่?
㉔ Voice/Proximity ถูกออกแบบสำหรับ Player จำนวนมากหรือไม่?
⑥⓪ ภาพรวม OneSync Infinity แบบเข้าใจง่าย
มอง Server ใหญ่แบบนี้
FXServer
│
1000+ Players
│
OneSync Infinity
│
┌──────────────┼──────────────┐
│ │ │
Object IDs Scope State
up to 65535 Focus Zone Awareness
│ ~424 units │
│ │ │
└──── Player/Entity Culling ──┘
│
Relevant State
│
┌────────┴────────┐
│ │
Client A Client B
│ │
Nearby entities Nearby entities
Client แต่ละคนไม่ได้รับโลก Multiplayer ทั้งหมด
แต่ได้รับเฉพาะส่วนที่เกี่ยวข้องกับตัวเอง
นี่คือหัวใจของ Infinity
ตัวอย่าง Global Player List ที่เหมาะกับ Infinity
server.lua
RegisterNetEvent(
'players:requestList',
function()
local src =
source
local result = {}
for _, playerId in ipairs(
GetPlayers()
) do
result[#result + 1] = {
id =
tonumber(
playerId
),
name =
GetPlayerName(
playerId
)
}
end
TriggerClientEvent(
'players:receiveList',
src,
result
)
end
)
Client ไม่ต้องพยายามสร้าง Global List จาก Local Scope
client.lua
RegisterNetEvent(
'players:receiveList',
function(players)
print(
'Players:',
#players
)
-- Update NUI
end
)
Flow คือ
Client
↓
Request
↓
Server
↓
Global Connected Players
↓
Filtered Result
↓
Client
เหมาะกับ Infinity Architecture มากกว่า
ตัวอย่าง Nearby Player Logic ฝั่ง Client
ถ้าต้องการทำ Nametag เฉพาะคนใกล้ตัว
CreateThread(function()
while true do
local sleep =
1000
local myPed =
PlayerPedId()
local myCoords =
GetEntityCoords(
myPed
)
for _, player in ipairs(
GetActivePlayers()
) do
if player ~=
PlayerId() then
local ped =
GetPlayerPed(
player
)
if DoesEntityExist(
ped
) then
local coords =
GetEntityCoords(
ped
)
local distance =
#(myCoords - coords)
if distance <
30.0 then
sleep = 0
-- Draw nearby UI
end
end
end
end
Wait(sleep)
end
end)
ตรงนี้ GetActivePlayers() เหมาะเพราะ Requirement คือ
Nearby Players ที่ Client รู้จัก
ไม่ใช่ Global Player List
นี่คือการเลือก API ให้ตรงกับ Infinity Model
คำถามที่พบบ่อยเกี่ยวกับ FiveM OneSync Infinity
FiveM OneSync Infinity คืออะไร
คือ OneSync Architecture สำหรับ Scale Player จำนวนมาก โดยใช้ Object ID Space ที่ใหญ่ขึ้นและ Player/Entity Culling ตาม Focus Zone
OneSync Infinity รองรับกี่คน
เอกสาร Cfx.re ปัจจุบันระบุสูงสุดถึงประมาณ 2,048 Players
เปิด 2,048 Slots แล้วรองรับได้ทันทีไหม
ไม่ ประสิทธิภาพจริงขึ้นกับ Hardware, Resources, Database, Network, Subscription และ Server Design
Object ID เพิ่มเป็นเท่าไร
เอกสารระบุจาก 8,192 เป็น 65,535
Focus Zone เท่าไร
เอกสารปัจจุบันระบุ Hardcoded ประมาณ 424 Game Units รอบ Player
Client เห็น Player ทุกคนหรือไม่
ไม่ Players ที่อยู่นอก Focus Zone ไม่จำเป็นต้องถูกสร้าง Local บน Client
GetActivePlayers คือ Player ทุกคนบน Server ไหม
ไม่ควรใช้ในความหมายดังกล่าวภายใต้ Infinity มันสะท้อน Players ที่ Client มี Local Representation ตาม Scope
ถ้าต้องการ Player ทุกคนทำอย่างไร
ทำ Server-side เช่นผ่าน GetPlayers() แล้วส่งข้อมูลที่ Client จำเป็นต้องใช้
Network ID ยังใช้ไหม
ใช้ และสำคัญสำหรับอ้าง Networked Entity ข้าม Client/Server
มี Network ID แล้ว Entity ต้องอยู่บน Client ไหม
ไม่ Entity อาจอยู่นอก Scope
Entity Owner เปลี่ยนได้ไหม
ได้เมื่อ Scope และ Networking State เปลี่ยน
คน Spawn Entity เป็น Owner ตลอดไหม
ไม่
State Bags เหมาะกับ Infinity ไหม
เหมาะมากสำหรับ Scoped State Replication ในหลาย Use Cases
playerEnteredScope ควรใช้ไหม
ใช้ได้แต่ Cfx.re เตือนเรื่อง Scaling Cost และแนะนำ State Bags เมื่อ Use Case เหมาะสม
Routing Bucket ยังใช้ได้ไหม
ได้ และทำงานร่วมกับ Scope/Culling
Bucket เดียวกันหมายความว่าเห็นกันทั่ว Map ไหม
ไม่ควรสมมติแบบนั้น Scope/Culling ยังมีผล
Infinity เป็น Anti-Cheat ไหม
ไม่
Infinity ช่วย Security อย่างไร
ช่วยให้ Server มี State Awareness มากขึ้น เช่นตรวจ Player Position/Entity State ฝั่ง Server แต่ Business Logic ยังต้อง Validate เอง
Infinity ทำให้ FPS สูงขึ้นไหม
Culling ช่วยลด Entity Processing ในหลายสถานการณ์ แต่ Script ที่เขียนไม่ดีหรือ Entity Density สูงยังทำ FPS ต่ำได้
Infinity ทำให้ Entity Unlimited ไหม
ไม่ Local Game/Streaming Limits ยังมีอยู่
Server 1,000 คนอยู่จุดเดียวกันได้สบายไหม
ไม่ควรคาดหวังแบบนั้น Player Density สูงยังสร้างภาระ Client, Network, Physics และ Voice อย่างมาก
ต้องใช้ set onesync on ไหม
เอกสารตั้งค่า FXServer ปัจจุบันใช้
set onesync on
เพื่อเปิด OneSync/Server-side State Awareness
สรุป FiveM OneSync Infinity คืออะไร
FiveM OneSync Infinity คือสถาปัตยกรรมที่ทำให้ FiveM สามารถ Scale ไปสู่ Server ผู้เล่นจำนวนมาก โดยไม่บังคับให้ Client แต่ละคนสร้างและ Synchronize Player กับ Entity ทั้ง Serverพร้อมกัน
เทคโนโลยีหลักประกอบด้วย
Object ID Space
8192
↓
65535
ร่วมกับ
Focus Zone
≈ 424 Game Units
และ
Player Culling
Ped Culling
Vehicle/Entity Culling
ดังนั้น
Server
→ อาจมี 1000+ Players
แต่
Client
→ รู้จักเฉพาะ Relevant Players/Entities
ผลกระทบต่อ Developer สำคัญมาก
อย่าเขียน Client Script โดยคิดว่า
GetActivePlayers()
=
Player ทุกคนใน Server
หากต้องการ Global Player Data ให้ทำฝั่ง Server
ในทางกลับกัน หากต้องการ Nearby Gameplay
Nametag
Nearby Interaction
3D Text
Local Player Effects
Client-side Scope กลับเป็นสิ่งที่เหมาะสม
Entity ก็เช่นเดียวกัน
Network ID
≠
Entity ต้องอยู่ใน Client เสมอ
จึงควรตรวจ Network Existence, Entity Existence และมี Timeout เมื่อต้องรอ Streaming
นอกจากนี้ Ownership สามารถ Migration เมื่อ Entity เข้าออก Scope ดังนั้น Resource ไม่ควรผูก Multiplayer Logic กับ Client Owner คนเดิมถาวร
สำหรับผู้ที่กำลังเรียน FiveM Developer กับ comsiam สิ่งที่ควรเปลี่ยนวิธีคิดหลังเข้าใจ Infinity คือ Client ไม่ได้เป็นสำเนาของ Server World ทั้งหมด แต่เป็นหน้าต่างที่เห็นเฉพาะส่วนของโลก Multiplayer ที่เกี่ยวข้องกับตัวเอง
หลักสำคัญจาก comsiam คือ Global Logic ให้อยู่ Server, Nearby Logic ให้อยู่ Client และใช้ OneSync Scope, Network ID, State Bags และ Server-side State Awareness ให้ตรงกับหน้าที่ของแต่ละระบบ
หัวข้อถัดไปคือ วิธีเปิด OneSync FiveM ซึ่งจะเข้าสู่การตั้งค่าจริงใน server.cfg, วิธีตรวจว่า OneSync ทำงานหรือไม่, sv_maxclients, Resource Constraint /onesync และปัญหาที่มักเกิดจากการใช้ Config เก่าหรือเข้าใจ OneSync Legacy/Infinity ผิด
Comments
Post a Comment