FiveM Entity คืออะไร

FiveM Entity คือสิ่งที่มีตัวตนอยู่ในโลกของ GTA V/FiveM และสามารถถูกอ้างอิงหรือจัดการด้วย Script ได้ เช่น Player Ped, NPC, Vehicle และ Object ต่าง ๆ

ตัวอย่าง Entity ที่พบมากที่สุดคือ

Ped
Vehicle
Object

เช่น Player Character เป็น Ped Entity

local ped =
    PlayerPedId()

รถที่ Player กำลังขับก็เป็น Vehicle Entity

local vehicle =
    GetVehiclePedIsIn(
        ped,
        false
    )

จากนั้น Entity สามารถถูกนำไปใช้กับ Native เช่น

GetEntityCoords(entity)
GetEntityHeading(entity)
DoesEntityExist(entity)

แต่สำหรับ Multiplayer สิ่งสำคัญมากคือ Entity Handle กับ Network ID ไม่ใช่สิ่งเดียวกัน

ถ้าต้องอ้าง Entity ข้าม Client หรือระหว่าง Client กับ Server ต้องเข้าใจ Network ID, Scope และ Entity Ownership เพิ่มเติม

① FiveM Entity คืออะไร

ใน FiveM คำว่า Entity ใช้อ้างถึง Game Object ที่มีตัวตนในโลกเกม

ตัวอย่างหลักคือ

Entity
├── Ped
├── Vehicle
└── Object

Ped, Vehicle และ Object จึงถือเป็น Entity ประเภทต่าง ๆ

Native หลายตัวใช้ Parameter แบบ Entity

เช่น

GetEntityCoords(entity)

จึงสามารถใช้กับ Ped, Vehicle หรือ Object ที่เหมาะสมได้

② Ped Entity คืออะไร

Ped คือ Character Entity

ตัวอย่าง

  • Player Character

  • Civilian NPC

  • Police NPC

  • Mission NPC

Player ของเราฝั่ง Client สามารถหา Ped ได้ด้วย

local ped =
    PlayerPedId()

ค่า ped ที่ได้คือ Entity Handle ของ Player Ped ใน Client Context นั้น

③ Vehicle Entity คืออะไร

Vehicle คือ Entity ประเภทรถ

เช่น

  • Car

  • Motorcycle

  • Truck

  • Helicopter

  • Plane

  • Boat

ตัวอย่างหา Vehicle ที่ Player อยู่

local ped =
    PlayerPedId()

local vehicle =
    GetVehiclePedIsIn(
        ped,
        false
    )

ค่า vehicle คือ Vehicle Entity Handle ใน Context นั้น

④ Object Entity คืออะไร

Object คือ Entity ประเภทสิ่งของหรือ Prop

ตัวอย่างเช่น

กล่อง
โต๊ะ
เก้าอี้
ป้าย
Barrier
Mission Prop

Script สามารถสร้าง Object แล้วจัดการ

  • Position

  • Rotation

  • Network State

  • Visibility

  • Attachment

ตาม Native และ Architecture ที่ใช้

⑤ Entity Handle คืออะไร

Entity Handle คือค่าที่ Script ใช้อ้างถึง Internal Game Representation ของ Entity ใน Context ปัจจุบัน

เช่น

local ped =
    PlayerPedId()

ค่า ped คือ Handle

หรือ

local vehicle =
    GetVehiclePedIsIn(
        ped,
        false
    )

ค่า vehicle ก็คือ Handle

จากนั้นสามารถส่ง Handle นี้ให้ Native อื่น

GetEntityCoords(vehicle)

⑥ Entity Handle เป็น ID ถาวรหรือไม่

ไม่

Entity Handle ไม่ควรถูกใช้เป็น Persistent ID ของรถหรือ Player

Cfx.re ระบุว่า Entity Handle เป็น Local Handle และ Entity เดียวกันสามารถมี Handle ต่างกันในแต่ละ Client ได้

ดังนั้นอย่าเก็บ

vehicleHandle = 123

ลง Database แล้วคิดว่า Server Restart หรือ Player คนอื่นจะใช้ 123 อ้างถึงรถคันเดิมได้

Entity Handle ไม่ได้ถูกออกแบบมาเพื่อสิ่งนั้น

⑦ Entity Handle เหมือนกันทุก Client ไหม

ไม่

สมมติรถคันเดียวกันอยู่ใน Scope ของ Player A และ Player B

อาจเกิด

Client A
Vehicle Handle = 125

Client B
Vehicle Handle = 386

ทั้งสอง Handle สามารถอ้างถึงรถ Networked Entity คันเดียวกันในแต่ละเครื่องได้

ดังนั้น

Entity Handle
=
Local Reference

ไม่ใช่ Global Multiplayer ID

⑧ ถ้าต้องอ้าง Entity ข้าม Client ใช้อะไร

ใช้ Network ID

แนวคิดคือ

Client A
Entity Handle
↓
Network ID
↓
Network
↓
Client B
↓
Entity Handle ของ Client B

FiveM มี Native สำหรับแปลงระหว่าง Entity Handle กับ Network ID

เช่น

NetworkGetNetworkIdFromEntity(
    entity
)

และ

NetworkGetEntityFromNetworkId(
    netId
)

⑨ Entity Handle กับ Network ID ต่างกันอย่างไร

จำง่าย ๆ

Entity Handle
→ Local Reference

Network ID
→ Network Reference

ถ้า Logic อยู่ Client เดียว

Entity Handle

มักเพียงพอ

ถ้าต้องส่ง Entity ไปอีก Client หรือ Server

Network ID

มักเป็น Identifier ที่เหมาะกว่า

⑩ ตัวอย่าง Entity Handle → Network ID

local vehicle =
    GetVehiclePedIsIn(
        PlayerPedId(),
        false
    )

if DoesEntityExist(vehicle) then

    local netId =
        NetworkGetNetworkIdFromEntity(
            vehicle
        )

    print(
        'Network ID:',
        netId
    )
end

ตอนนี้ netId สามารถใช้เป็น Network Reference ตามระบบที่เหมาะสม

⑪ Network ID → Entity Handle

อีก Client สามารถรับ Network ID แล้วแปลง

local entity =
    NetworkGetEntityFromNetworkId(
        netId
    )

สำหรับ Vehicle ยังมี Alias อย่าง

NetToVeh(netId)

Ped ก็มี API ที่เกี่ยวข้องตามประเภท Entity

แต่ต้องตรวจก่อนว่า Entity อยู่ใน Scope และมีอยู่จริง

⑫ Network ID เป็น Persistent ID หรือไม่

ไม่

Cfx.re ระบุว่า Entity Network ID เป็น Integer แบบ 16-bit ที่สามารถถูกนำกลับมาใช้ใหม่หลัง Entity เดิมหมดอายุ

ดังนั้น Network ID ควรใช้

ระหว่าง Lifetime ของ Entity

ไม่ควรบันทึกลง Database เพื่อเป็น Permanent Vehicle Identifier

รถถาวรควรใช้ข้อมูลอย่าง

Database ID
Plate
UUID
Framework Vehicle ID

ตาม Architecture

⑬ Entity อยู่ใน Scope คืออะไร

ใน Multiplayer Client ไม่จำเป็นต้องมี Entity ทุกตัวใน Server อยู่ในเครื่องตลอดเวลา

OneSync ใช้ระบบ Scope/Culling เพื่อส่ง Entity ที่เกี่ยวข้องให้ Client

แนวคิดคือ

Entity อยู่ใกล้ / อยู่ใน Scope
→ Client มี Entity

Entity อยู่นอก Scope
→ Client อาจไม่มี Entity Local

นี่ช่วยลด Network และ Processing Load

⑭ ทำไมมี Network ID แต่หา Entity ไม่เจอ

เพราะ Entity อาจไม่ได้อยู่ใน Scope ของ Client นั้น

Cfx.re ระบุว่า Network ID หนึ่งไม่ได้หมายความว่า Entity นั้นต้องมีอยู่ใน Client ทุกคนเสมอ

ดังนั้นก่อนใช้ Network ID ควรตรวจ

NetworkDoesEntityExistWithNetworkId(
    netId
)

ตาม Use Case

อย่าคิดว่า

มี Net ID
=
มี Entity Handle แน่นอน

⑮ DoesEntityExist คืออะไร

DoesEntityExist() ใช้ตรวจว่า Entity Handle มี Entity ที่ Valid อยู่หรือไม่

ตัวอย่าง

if DoesEntityExist(vehicle) then
    print('Vehicle exists')
end

เหมาะก่อนทำ Action กับ Entity ที่อาจถูกลบหรือหายไปแล้ว

⑯ ทำไมต้องตรวจ DoesEntityExist

สมมติ Script เก็บ

local vehicle =
    someVehicle

หลังจากนั้นรถอาจถูก

  • Delete

  • Despawn

  • Resource Cleanup

  • Mission Cleanup

  • Network Scope Change ในบาง Context

ถ้า Code ภายหลังยังใช้ Handle โดยไม่ตรวจ อาจเกิด Behavior ที่ไม่ถูกต้อง

Pattern ที่ปลอดภัยกว่า

if not DoesEntityExist(vehicle) then
    return
end

⑰ Entity Handle ไม่ใช่ Player Server ID

นี่เป็น Error ที่มือใหม่เจอบ่อย

ตัวอย่าง

local ped =
    PlayerPedId()

ped ไม่ใช่ Server ID ของ Player

ถ้าต้องการ Server ID ฝั่ง Client ใช้ API ที่เกี่ยวข้อง เช่นแปลง Player Index เป็น Server ID

จึงต้องแยก

Ped Handle
Player Index
Server ID
Network ID

ให้ถูกต้อง

⑱ Player Ped เป็น Networked Entity ไหม

โดยปกติ Player จะมี Ped ที่เป็น Networked Entity

Cfx.re ระบุว่า Player Ped เป็น Standard Network Object และมี Network ID

ดังนั้น Player มีทั้ง Concept

Player
+
Ped Entity

ซึ่งไม่ใช่สิ่งเดียวกัน

⑲ Player กับ Ped ต่างกันอย่างไร

Player คือ Player Identity/Connection ใน Game Context

Ped คือ Physical Character Entity

ตัวอย่าง Client

Player
→ Player Index

Ped
→ Entity Handle

Server มักใช้

source

เป็น Player Server ID

แล้วสามารถหา Player Ped ผ่าน Native ที่รองรับ

จึงไม่ควรใช้คำว่า Player ID, Ped ID และ Entity ID แทนกันโดยไม่แยกความหมาย

⑳ วิธีหา Player Ped ฝั่ง Server

เมื่อ Server มี Player Source

local src =
    source

สามารถหา Ped ตาม Server-side API ที่รองรับ

local ped =
    GetPlayerPed(src)

จากนั้น

local coords =
    GetEntityCoords(ped)

สามารถใช้กับ OneSync/State Awareness ที่เหมาะสม

มีประโยชน์มากสำหรับ Server-side Position Validation

㉑ Entity Coordinates คืออะไร

Entity มีตำแหน่งในโลก

สามารถหาได้ด้วย

local coords =
    GetEntityCoords(entity)

ค่าที่ได้เป็น Coordinates เช่น

x
y
z

Use Case เช่น

  • Distance Check

  • Garage

  • Shop

  • Mission

  • Teleport

  • Zone Validation

㉒ Entity Heading คืออะไร

Heading คือทิศทางที่ Entity หัน

สามารถอ่านด้วย

local heading =
    GetEntityHeading(entity)

ใช้กับ

  • Spawn Vehicle

  • Spawn Ped

  • Teleport

  • Placement

  • Garage

เช่น Spawn Vehicle ให้หันตามจุดจอด

㉓ Entity Model คืออะไร

Entity แต่ละตัวมี Model

เช่น Vehicle Model

sultan
adder
blista

Ped หรือ Object ก็มี Model ของตัวเอง

Script มักใช้ Model Hash ในการสร้าง Entity

เช่น

local model =
    joaat('sultan')

จากนั้น Request Model ก่อนสร้าง Client-side Entityตาม Workflow

㉔ Local Entity คืออะไร

Local Entity คือ Entity ที่ถูกสร้างหรือใช้เฉพาะ Client Context โดยไม่ได้ Network ไปให้ผู้เล่นอื่น

ตัวอย่าง Use Case

  • Preview Vehicle

  • Client-only Prop

  • Temporary Visual

  • Local Effect

ผู้เล่นอื่นไม่จำเป็นต้องเห็น Entity นั้น

จึงไม่ต้องทำทุก Entity ให้เป็น Networked Entity

㉕ Networked Entity คืออะไร

Networked Entity คือ Entity ที่ถูก Sync ผ่าน Network Layer

เช่นรถที่ผู้เล่นหลายคนต้องเห็นคันเดียวกัน

Concept

Entity
↓
Network ID
↓
OneSync / Network Layer
↓
Relevant Clients

Networked Entity มีเรื่องเพิ่มเติม เช่น

  • Network ID

  • Ownership

  • Scope

  • Migration

  • State

  • Persistence

㉖ Local Entity กับ Networked Entity เลือกอะไร

ถามก่อนว่า

ผู้เล่นคนอื่นต้องเห็นหรือโต้ตอบกับ Entity นี้ไหม?

ถ้าไม่

Local Entity

อาจเหมาะกว่า

ถ้าต้อง Sync ระหว่างผู้เล่น

Networked Entity

จึงเหมาะ

อย่าทำ Prop ตกแต่งชั่วคราวทุกชิ้นเป็น Networked Entity โดยไม่มีเหตุผล

㉗ Entity Ownership คืออะไร

Networked Entity ต้องมี Concept ว่า Client/Server ใดมี Network Control หรือ Ownership ตามระบบ

Ownership มีผลกับ

  • Physics

  • Movement

  • Native Actions

  • Sync

  • Migration

ใน OneSync Ownership สามารถเปลี่ยนเมื่อ Entity เข้า/ออก Scope หรือมีการ Migration

ดังนั้นอย่าสมมติว่า Client ที่สร้าง Entity จะเป็น Owner ตลอดไป

หัวข้อนี้จะลงรายละเอียดในบทความ 431

㉘ Entity Ownership กับ Script Ownership เหมือนกันไหม

ไม่ควรใช้คำสองอย่างนี้ปนกัน

Network Ownership เกี่ยวกับการ Sync/Control Entity ใน Network

Script Ownership เกี่ยวข้องกับ Resource/Script Lifecycle และ Mission Entity Behavior ในบางระบบ

เมื่อทำระบบ Entity ขั้นสูงต้องดู Documentation ของ Native และ OneSync ให้ตรงกับสิ่งที่ต้องการจริง ๆ

㉙ Entity Migration คืออะไร

เมื่อ Network Ownership เปลี่ยนจาก Client หนึ่งไปอีก Client หนึ่ง เรียกว่า Ownership Migration ในแนวคิด Networking

ตัวอย่าง

Client A อยู่ใกล้รถ
→ A Control

A ออกนอก Scope
↓
Entity Ownership เปลี่ยน
↓
Client B อาจ Control

ดังนั้น Architecture ไม่ควรผูก Entity Logic สำคัญกับ Owner Client คนเดิมตลอดเวลา

㉚ OneSync เกี่ยวข้องกับ Entity อย่างไร

OneSync เป็นระบบ Synchronization ของ FiveM ที่จัดการ Networked Entities และ Player State ใน Multiplayer

ช่วยเรื่อง

  • Server-side Entity State

  • Entity Scope

  • Ownership

  • Culling

  • Server-created Entities

  • State Bags

  • Routing Buckets

Entity Development ใน FiveM Server ปัจจุบันจึงสัมพันธ์กับ OneSync อย่างมาก

㉛ Culling คืออะไร

Culling คือการไม่ส่งหรือไม่สร้าง Entity ที่ไม่จำเป็นบน Client ที่อยู่นอกขอบเขตความสนใจ

ตัวอย่าง

Player กรุงเทพจำลอง

ไม่จำเป็นต้องมี Entity ทุกตัวของผู้เล่นที่อยู่อีกด้านของแผนที่อยู่ใน Client Memory/Sync Context พร้อมกัน

OneSync ใช้ Scope เพื่อช่วยลดข้อมูลที่ไม่จำเป็น

㉜ Entity ออกจาก Scope เกิดอะไรขึ้น

Client อาจไม่มี Local Representation ของ Entity นั้นอีก

ดังนั้น Handle บางอย่างไม่ควรถูกถือว่า Valid ตลอดไปเมื่อใช้ในระบบ Networked Entity

ถ้าต้องอ้าง Entity ข้าม Scope/Client ให้ใช้ Network Architecture ที่เหมาะสม

และตรวจ Entity Existence ก่อนใช้งาน

㉝ Network ID เปลี่ยนตอน Ownership Migration ไหม

Cfx.re ระบุว่า Network ID จะไม่เปลี่ยนตลอด Lifetime ของ Network Entity นั้น

แม้ Ownership จะสามารถ Migration ได้

ดังนั้น Network ID เหมาะกว่า Entity Handle สำหรับอ้าง Entity ข้ามเครื่องในช่วง Lifetime เดียวกัน

แต่หลัง Entity ถูกลบ Network ID สามารถถูกนำกลับมาใช้กับ Entity อื่นในอนาคตได้

㉞ Entity Handle เปลี่ยนได้ไหม

ได้

Cfx.re ระบุว่า Entity เดียวกันหากถูก Recreated Locally หรือ Remotely สามารถได้รับ Handle ใหม่ได้

ดังนั้น Script ที่เก็บ Handle ระยะยาวควรตรวจ Validity และ Lifecycle

อย่าพึ่ง Number ของ Handle เป็น Identity ถาวร

㉟ วิธีส่งรถจาก Client ไป Server

ไม่ควรส่ง Local Entity Handle แล้วสมมติ Server จะตีความเป็น Entity เดียวกันเสมอ

Pattern ที่เหมาะกว่าใน Network Use Case คือ

Client

local vehicle =
    GetVehiclePedIsIn(
        PlayerPedId(),
        false
    )

if not DoesEntityExist(vehicle) then
    return
end

local netId =
    NetworkGetNetworkIdFromEntity(
        vehicle
    )

TriggerServerEvent(
    'garage:store',
    netId
)

จากนั้น Server ตรวจ Entity ตาม Network ID/Server API ที่เหมาะสม

㊱ ส่ง Entity Handle ไป Client คนอื่นดีไหม

ไม่

เพราะ Handle ของ Client A ไม่จำเป็นต้องตรงกับ Handle ของ Client B

ควรส่ง

Network ID

ตัวอย่าง

TriggerClientEvent(
    'vehicle:update',
    target,
    netId
)

Client เป้าหมายจึง Resolve Network ID เป็น Local Entity Handle ของตัวเอง

㊲ ตัวอย่าง Server → Client Vehicle Network ID

Server

TriggerClientEvent(
    'vehicle:highlight',
    target,
    netId
)

Client

RegisterNetEvent(
    'vehicle:highlight',
    function(netId)

        if not NetworkDoesEntityExistWithNetworkId(
            netId
        ) then
            return
        end

        local vehicle =
            NetToVeh(netId)

        if not DoesEntityExist(vehicle) then
            return
        end

        -- vehicle logic

    end
)

นี่เป็น Pattern ที่เข้าใจ Local Handle กับ Network ID ถูกต้องกว่า

㊳ Server-created Entity คืออะไร

OneSync รองรับการสร้าง Entity บางประเภทจาก Server

เช่น

  • Vehicle

  • Ped

  • Object

ตาม Native/API ที่รองรับ

Cfx.re แนะนำ Server-created Entities เป็น Best Practice สำหรับหลายระบบที่ Server ต้องการควบคุม Entity อย่างเป็น Authority

㊴ ทำไม Server-created Entity น่าสนใจ

เพราะช่วยให้ Server เป็นผู้ควบคุมการสร้าง Entity มากขึ้น

ตัวอย่าง Mission Vehicle

แทน

Client:
Spawn Vehicle เอง
↓
บอก Server ว่าสร้างแล้ว

สามารถออกแบบ

Server:
Validate Request
↓
Create Entity
↓
กำหนด State
↓
Clients รับ Sync

ช่วยลด Client Authority ในระบบสำคัญ

㊵ ตัวอย่าง Server-side Create Vehicle

Cfx.re ยกตัวอย่าง OneSync ด้วย

local vehicle =
    CreateVehicleServerSetter(
        GetHashKey('blista'),
        'automobile',
        2204.795,
        -887.9213,
        1461.224,
        90.0
    )

จากนั้นสามารถจัด Persistence/Orphan Mode ตาม Requirement

Server-created Entity เหมาะกับระบบที่ Server ต้องเป็นผู้ Author Entity

㊶ SetEntityOrphanMode คืออะไร

สำหรับ Server-created Entity สามารถใช้ Orphan Mode ตาม OneSync API เพื่อควบคุมพฤติกรรมเมื่อ Entity ไม่มี Client Owner

Cfx.re แนะนำ KeepEntity Mode สำหรับกรณีที่ต้องการให้ Server ไม่ลบ Entity เพราะไม่มี Owner

ตัวอย่าง

SetEntityOrphanMode(
    vehicle,
    2
)

แต่ Entity Persistence จริงยังต้องออกแบบ Lifecycle และ Cleanup ให้ครบ

㊷ Persistent Entity ไม่ใช่ Database Persistence

คำว่า Persistent ใน Entity Networking ไม่ได้แปลว่า Entity จะอยู่ข้าม Server Restart โดยอัตโนมัติ

ถ้าต้องการรถกลับมาหลัง Restart ต้องเก็บข้อมูลใน Persistent Storage เช่น Database

แล้วสร้าง Entity ใหม่เมื่อ Server เริ่มหรือเมื่อจำเป็น

แยก

Runtime Entity Persistence

กับ

Database Persistence

ให้ออกจากกัน

㊸ Entity Cleanup สำคัญไหม

สำคัญมาก

ถ้า Script สร้าง

  • Vehicles

  • Peds

  • Objects

จำนวนมากแต่ไม่ Cleanup อาจเกิด

  • Entity สะสม

  • Network Load

  • Memory Usage

  • World Clutter

  • Performance ลดลง

Resource ควรมี Lifecycle ชัดเจนว่า Entity ถูกสร้างเมื่อไรและลบเมื่อไร

㊹ Temporary Entity ควรลบเมื่อไร

ตัวอย่าง Mission Prop

Mission Start
↓
Create Prop
↓
Mission Running
↓
Mission Complete / Cancel
↓
Delete Entity

ไม่ควรปล่อย Prop อยู่ตลอดหลัง Mission จบ

ยกเว้น Entity นั้นตั้งใจเป็น Persistent World Entity

㊺ DeleteEntity ใช้ทำอะไร

ใช้ลบ Entity ที่ Script มีสิทธิ์จัดการตาม Context

ตัวอย่าง

if DoesEntityExist(entity) then
    DeleteEntity(entity)
end

แต่กับ Networked Entity ต้องคิดเรื่อง

  • Ownership

  • Network Control

  • Server Authority

  • Persistence

ด้วย

ไม่ควร Delete Network Entity จาก Clientโดยไม่ออกแบบสิทธิ์ให้เหมาะสม

㊻ Entity Security สำคัญอย่างไร

Client สามารถพยายามสร้างหรือจัดการ Entity ในบางระบบได้

Cfx.re มี OneSync Entity Lockdown เพื่อจำกัด Client-created Entities ตาม Routing Bucket

มี Mode เช่น

strict
relaxed
inactive

และในบางบริบทมี Mode เพิ่มเติมตาม Server/Game Version

ใช้เมื่อ Server ต้องการควบคุม Entity Creation อย่างเข้มงวด

㊼ Entity Lockdown แบบ strict คืออะไร

OneSync Documentation ระบุว่า

strict

จะไม่อนุญาตให้ Client สร้าง Entity ใน Routing Bucket นั้น

แนวคิดคือ

Client
→ ขอ Spawn

Server
→ Validate

Server
→ Create Entity

เหมาะกับระบบที่ต้องการ Server-authoritative Entity Creation

รายละเอียดจะลงลึกในหัวข้อ 440

㊽ Routing Bucket กับ Entity

Routing Bucket ใช้แยก Player และ Entity ออกเป็น Instance/Dimension

ตัวอย่าง

Bucket 0
→ Main World

Bucket 10
→ Mission A

Bucket 20
→ Character Selection

Entity ที่อยู่ Bucket หนึ่งจะถูกจัดการตาม Routing Policy ของ Bucket นั้น

จึงมีประโยชน์กับ Instance System

㊾ Entity อยู่ Bucket ไหนตรวจได้ไหม

FiveM มี Routing Bucket API สำหรับ Server-side Entity/Player

ใช้ตรวจหรือกำหนดว่า Entity อยู่ Bucket ไหน

ระบบ Instance ที่ดีต้องจัด Player และ Entity ให้สัมพันธ์กัน

เช่น Mission Vehicle ควรอยู่ Bucket เดียวกับ Mission Players ตาม Architecture

㊿ State Bag กับ Entity คืออะไร

Network Entity สามารถมี State Bag

ใช้เก็บ State ที่สามารถ Replicate ตาม Policy ของ FiveM

ตัวอย่าง Concept

Vehicle
├── fuel
├── locked
└── customState

แทนการ Broadcast Event ซ้ำทุกครั้งสำหรับข้อมูล State บางประเภท

State Bags จะลงรายละเอียดในหัวข้อ 432

51 Entity State กับ Event ต่างกันอย่างไร

Event เหมาะกับ

Something happened

เช่น

door opened
explosion happened
mission completed

State เหมาะกับ

Something currently is

เช่น

locked = true
fuel = 75
duty = true

Entity State Bags จึงเหมาะกับข้อมูลสถานะบางชนิด

52 Entity กับ ESX เกี่ยวข้องอย่างไร

ESX จัดการ Framework State เช่น

  • Player Data

  • Job

  • Economy

แต่เมื่อ Resource ต้องจัด

  • Ped

  • Vehicle

  • Object

  • Position

ก็ยังใช้ FiveM/GTA Entity และ Native ตามปกติ

Framework ไม่ได้แทน Entity System

53 Entity กับ QBCore เกี่ยวข้องอย่างไร

เหมือนกัน

QBCore สามารถมี Vehicle/Player APIs ของตัวเอง

แต่ Vehicle ในโลก FiveM ยังเป็น Entity

จึงยังต้องเข้าใจ

Entity Handle
Network ID
Ownership
Scope

เพื่อ Debug Multiplayer Script ได้อย่างถูกต้อง

54 Entity กับ Qbox เกี่ยวข้องอย่างไร

Qbox/ox ecosystem สามารถช่วยเรื่อง Framework และ Library Layer

แต่ Core Multiplayer Entity ยังเป็น FiveM Entity System

ดังนั้น Developer ที่เข้าใจ Entity Core จะสามารถอ่านและแก้ Script ได้ดีขึ้น ไม่ว่าจะใช้ Framework ใด

55 Entity Handle เก็บใน Global Variable ได้ไหม

ได้ถ้าเข้าใจ Lifecycle

เช่น

local missionVehicle = nil

ตอนสร้าง

missionVehicle =
    vehicle

ตอนใช้

if missionVehicle
and DoesEntityExist(
    missionVehicle
) then

    -- logic

end

ตอน Mission จบควร Reset/Cleanup

missionVehicle = nil

อย่าถือว่า Handle เก่าจะ Valid ตลอด Resource Lifetime

56 Entity Handle เก็บใน Database ได้ไหม

ไม่ควร

เช่นไม่ควรบันทึก

entity_handle = 425

เป็น Identity ของรถถาวร

เพราะ Entity Handle เป็น Runtime-local Reference

ควรใช้ Persistent Identifier เช่น

vehicle_id
plate
uuid
owner_id
model

แล้วสร้าง/ค้น Runtime Entity เมื่อจำเป็น

57 Network ID เก็บใน Database ได้ไหม

ไม่ควรใช้เป็น Permanent Identity เช่นกัน

Network ID มีประโยชน์ใน Lifetime ของ Entity

แต่สามารถถูก Reuse หลัง Entity ถูกลบ

Database ควรเก็บ Persistent Identifier ที่ระบบของคุณควบคุมเอง

58 Entity Debug อย่างไร

เริ่มจากตรวจ Handle

local vehicle =
    GetVehiclePedIsIn(
        PlayerPedId(),
        false
    )

print(
    'handle:',
    vehicle
)

ตรวจ Exist

print(
    'exists:',
    DoesEntityExist(vehicle)
)

หา Network ID

if DoesEntityExist(vehicle) then

    local netId =
        NetworkGetNetworkIdFromEntity(
            vehicle
        )

    print(
        'netId:',
        netId
    )
end

ช่วยแยกปัญหาว่าอยู่ที่ Handle หรือ Networking

59 Checklist ก่อนจัดการ FiveM Entity

ก่อนเขียนระบบ Entity ให้ถาม

① Entity เป็น Ped, Vehicle หรือ Object?
② Entity เป็น Local หรือ Networked?
③ Handle นี้อยู่ Client ไหน?
④ ต้องส่ง Entity ข้าม Client/Server หรือไม่?
⑤ ถ้าต้องส่ง ใช้ Network ID หรือยัง?
⑥ Entity อยู่ใน Scope หรือไม่?
⑦ ตรวจ DoesEntityExist หรือยัง?
⑧ Network ID ยัง Valid หรือไม่?
⑨ Entity Owner คือใคร?
⑩ Ownership สามารถ Migration ได้หรือไม่?
⑪ Entity ถูกสร้าง Client หรือ Server?
⑫ ต้อง Persistent ใน Runtime หรือไม่?
⑬ ต้องเก็บ Database หรือไม่?
⑭ ต้อง Cleanup เมื่อไร?
⑮ Entity อยู่ Routing Bucket ไหน?
⑯ ต้องมี State Bag หรือไม่?
⑰ Client มีสิทธิ์สร้าง Entity นี้หรือไม่?
⑱ ต้องใช้ Entity Lockdown หรือไม่?

หากตอบคำถามเหล่านี้ได้ Entity System จะมีปัญหาน้อยลงมาก

⑥⓪ หลักจำ FiveM Entity แบบง่ายที่สุด

จำโครงสร้างนี้

Ped
Vehicle
Object
↓
ทั้งหมดเป็น Entity

และ

Entity Handle
=
Local Reference

ถ้าต้องข้าม Network

Entity Handle
↓
Network ID
↓
อีก Client / Server
↓
Local Entity Handle

สุดท้าย

Network ID
≠
Permanent Database ID

นี่คือพื้นฐานสำคัญที่สุดก่อนเข้าสู่ FiveM Networking ขั้นต่อไป

ตัวอย่าง Entity + Network ID แบบสมบูรณ์

client.lua

RegisterCommand(
    'myvehicle',
    function()

        local ped =
            PlayerPedId()

        local vehicle =
            GetVehiclePedIsIn(
                ped,
                false
            )

        if not DoesEntityExist(
            vehicle
        ) then

            print(
                'No vehicle'
            )

            return
        end

        local coords =
            GetEntityCoords(
                vehicle
            )

        local heading =
            GetEntityHeading(
                vehicle
            )

        local netId =
            NetworkGetNetworkIdFromEntity(
                vehicle
            )

        print(
            'Handle:',
            vehicle
        )

        print(
            'Network ID:',
            netId
        )

        print(
            'Coords:',
            coords
        )

        print(
            'Heading:',
            heading
        )

    end,
    false
)

จาก Code นี้จะเห็นว่า Vehicle หนึ่งคันสามารถมีข้อมูลหลายแบบ

Vehicle Entity
↓
Handle
↓
Coordinates
↓
Heading
↓
Network ID

แต่แต่ละค่ามีหน้าที่ต่างกัน

คำถามที่พบบ่อยเกี่ยวกับ FiveM Entity

FiveM Entity คืออะไร

คือ Game Object ที่ Script สามารถอ้างอิงและจัดการได้ เช่น Ped, Vehicle และ Object

Ped เป็น Entity ไหม

เป็น

Vehicle เป็น Entity ไหม

เป็น

Object เป็น Entity ไหม

เป็น

Entity Handle คืออะไร

คือ Local Runtime Handle ที่ใช้อ้างถึง Internal Game Entity ใน Context ปัจจุบัน

Entity Handle เหมือนกันทุก Client ไหม

ไม่ Entity เดียวกันสามารถมี Handle ต่างกันใน Client แต่ละคนได้

Entity Handle เก็บใน Database ได้ไหม

ไม่ควร เพราะไม่ได้เป็น Persistent Identifier

Network ID คืออะไร

คือ Identifier สำหรับอ้าง Networked Entity ข้ามเครื่องในช่วง Lifetime ของ Entity

Network ID เหมือน Entity Handle ไหม

ไม่

Network ID เก็บใน Database เป็น ID ถาวรได้ไหม

ไม่ควร เพราะ Network ID สามารถถูก Reuse หลัง Entity หมด Lifetime

วิธีแปลง Entity เป็น Network ID

ใช้ Native เช่น

NetworkGetNetworkIdFromEntity(
    entity
)

วิธีแปลง Network ID เป็น Entity

ใช้

NetworkGetEntityFromNetworkId(
    netId
)

หรือ Alias ตามประเภท Entity เช่น NetToVeh()

ทำไมมี Network ID แต่ Client หา Entity ไม่เจอ

เพราะ Entity อาจไม่ได้อยู่ใน Scope ของ Client นั้น

ตรวจ Entity มีอยู่ไหม

ใช้

DoesEntityExist(entity)

Player Ped เป็น Entity ไหม

เป็น Ped Entity และ Player Ped โดยปกติเป็น Networked Entity

source เป็น Entity ไหม

ไม่ source ฝั่ง Server เป็น Player Server ID ไม่ใช่ Entity Handle

OneSync เกี่ยวกับ Entity ไหม

เกี่ยวโดยตรงกับ Entity Synchronization, Scope, Ownership, Server-created Entities, State และ Routing

Server สร้าง Entity ได้ไหม

OneSync รองรับ Server-created Ped, Vehicle และ Object ใน Use Case ที่ Native/API รองรับ

Entity Ownership คืออะไร

คือแนวคิดเกี่ยวกับผู้ที่ควบคุม Networked Entity ใน Network Layer ซึ่งสามารถ Migration ได้ตาม Scope และระบบ OneSync

Entity Lockdown คืออะไร

เป็นระบบ OneSync สำหรับจำกัดการสร้าง Entity จาก Client ตาม Routing Bucket และ Lockdown Mode

สรุป FiveM Entity คืออะไร

FiveM Entity คือสิ่งที่มีตัวตนอยู่ในโลกเกม เช่น Ped, Vehicle และ Object ซึ่ง Script สามารถอ้างอิงและจัดการผ่าน Entity Handle และ Native ต่าง ๆ

โครงสร้างพื้นฐานคือ

Entity
├── Ped
├── Vehicle
└── Object

ตัวอย่าง

local ped =
    PlayerPedId()

local coords =
    GetEntityCoords(ped)

แต่เมื่อเข้าสู่ Multiplayer ต้องเข้าใจความแตกต่างระหว่าง

Entity Handle

กับ

Network ID

โดย

Entity Handle
→ Local ต่อ Client/Runtime Context

ส่วน

Network ID
→ ใช้อ้าง Networked Entity ข้ามเครื่อง

Entity เดียวกันสามารถมี Handle คนละเลขใน Client แต่ละคนได้ ดังนั้นหาก Client A ต้องบอกรถคันหนึ่งให้ Client B หรือ Server รู้จัก ไม่ควรส่ง Local Handle ไปเป็น Global Identity แต่ควรใช้ Network ID ตาม Networking Architecture

อย่างไรก็ตาม Network ID ก็ไม่ใช่ Database ID ถาวร เพราะสามารถถูกนำกลับมาใช้ใหม่หลัง Entity เดิมถูกลบได้

เมื่อใช้ OneSync ยังต้องเข้าใจเรื่อง

Scope
Culling
Ownership
Migration
Server-created Entity
State Bags
Routing Buckets
Entity Lockdown

เพิ่มขึ้นอีก

สำหรับคนที่เรียน FiveM Developer กับ comsiam จุดที่สำคัญที่สุดของบทนี้คือ อย่าเรียกตัวเลขทุกอย่างว่า Entity ID เพราะ Player Source, Entity Handle และ Network ID เป็นคนละสิ่งกัน และการสับสนระหว่างสามอย่างนี้เป็นสาเหตุของ Bug ใน Multiplayer Script จำนวนมาก

บทความถัดไปของ comsiam จะเจาะเรื่องนี้ต่อทันทีในหัวข้อ FiveM Network ID คืออะไร ว่า Net ID ถูกสร้างอย่างไร ใช้ข้าม Client/Server อย่างไร ทำไม Entity อาจไม่อยู่ใน Scope และทำไม Network ID จึงไม่ควรถูกใช้เป็น Permanent Database ID

Comments

Popular posts from this blog

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

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

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