Networked Particle Effects in FiveM — Sync for everyone to see
Networked Particle Effects in FiveM
Client-side effects only visible to one player — Networked Effects require an event system to be synced for everyone to see at the same time.
Why are Networked Effects important?
client A shoots an explosion → client A sees an explosion
client B, C don't see anything ❌
Edit: server relay → broadcast → every client plays effect at the same time ✅
Basic Pattern: Server Relay
-- ===== client.lua =====
-- send to server
local function RequestNetworkEffect(effectName, dictName, coords, scale)
TriggerServerEvent("myScript:playEffect", {
effect = effectName,
dict = dictName,
x = coords.x,
y = coords.y,
z = coords.z,
scale = scale or 1.0
})
end
-- Receive from server and play.
RegisterNetEvent("myScript:broadcastEffect")
AddEventHandler("myScript:broadcastEffect", function(data)
Citizen.CreateThread(function()
RequestNamedPtfxAsset(data.dict)
while not HasNamedPtfxAssetLoaded(data.dict) do
Citizen.Wait(0)
end
UseParticleFxAssetNextCall(data.dict)
StartParticleFxNonLoopedAtCoord(
data.effect,
data.x, data.y, data.z,
0.0, 0.0, 0.0,
data.scale,
false, false, false
)
end)
end)
-- ===== server.lua =====
RegisterNetEvent("myScript:playEffect")
AddEventHandler("myScript:playEffect", function(data)
-- Broadcast to every client in the area
TriggerClientEvent("myScript:broadcastEffect", -1, data)
end)
Distance-based Broadcasting
Send only nearby players, not the entire server:
-- server.lua
local function GetPlayersNearCoords(coords, radius)
local nearbyPlayers = {}
local x, y, z = coords.x, coords.y, coords.z
for _, playerId in ipairs(GetPlayers()) do
local ped = GetPlayerPed(playerId)
local px, py, pz = table.unpack(GetEntityCoords(ped))
local distance = math.sqrt(
(px-x)^2 + (py-y)^2 + (pz-z)^2
)
if distance <= radius then
table.insert(nearbyPlayers, playerId)
end
end
return nearbyPlayers
end
RegisterNetEvent("myScript:playEffect")
AddEventHandler("myScript:playEffect", function(data)
local source = source
local coords = vector3(data.x, data.y, data.z)
-- Send only to people within 100 units
local nearbyPlayers = GetPlayersNearCoords(coords, 100.0)
for _, playerId in ipairs(nearbyPlayers) do
TriggerClientEvent("myScript:broadcastEffect", playerId, data)
end
end)
Looped Networked Effect
For looped effects, start/stop must be handled:
-- client.lua
local activeEffects = {}
RegisterNetEvent("myScript:startLoopedEffect")
AddEventHandler("myScript:startLoopedEffect", function(data)
Citizen.CreateThread(function()
if not SafeRequestPtfx(data.dict) then return end
UseParticleFxAssetNextCall(data.dict)
local handle = StartParticleFxLoopedAtCoord(
data.effect,
data.x, data.y, data.z,
0.0, 0.0, 0.0,
data.scale,
false, false, false, false
)
-- Store handle with effect ID
activeEffects[data.effectId] = handle
end)
end)
RegisterNetEvent("myScript:stopLoopedEffect")
AddEventHandler("myScript:stopLoopedEffect", function(effectId)
if activeEffects[effectId] then
StopParticleFxLooped(activeEffects[effectId], false)
activeEffects[effectId] = nil
end
end)
-- server.lua
local effectCounter = 0
RegisterNetEvent("myScript:requestLoopedEffect")
AddEventHandler("myScript:requestLoopedEffect", function(data)
effectCounter = effectCounter + 1
data.effectId = "effect_" .. effectCounter
-- Broadcast start
TriggerClientEvent("myScript:startLoopedEffect", -1, data)
-- Auto-stop after 10 seconds
SetTimeout(10000, function()
TriggerClientEvent("myScript:stopLoopedEffect", -1, data.effectId)
end)
end)
Native Networked Functions
FiveM has native functions for direct networked effects:
-- Non-looped networked (runs on a client that can be called but can sync)
StartNetworkedParticleFxNonLoopedAtCoord(
effectName,
x, y, z,
rotX, rotY, rotZ,
scale,
xAxis, yAxis, zAxis
)
-- Looped networked
local handle = StartNetworkedParticleFxLoopedAtCoord(
effectName,
x, y, z,
rotX, rotY, rotZ,
scale,
xAxis, yAxis, zAxis,
false
)
Summary
| Pattern | used when |
|---|---|
| TriggerClientEvent -1 | Everyone must see |
| Distance-based | Save bandwidth |
| Native networked | quick sync without event |
Choose a pattern that suits your use case — important effects should use a server relay for accuracy.
Related Articles
วิธีจัดการ Version และ Update Script ในเซิร์ฟเวอร์ FiveM อย่างมืออาชีพ
อัพเดท script บน production โดยไม่ให้เซิร์ฟเวอร์ down — เรียนรู้ระบบจัดการ version, Git workflow, และกลยุทธ์ deploy ที่ลดความเสี่ยง
หลักการ Clean Code สำหรับ FiveM Script Developer
โค้ดที่ทำงานได้กับโค้ดที่ดีไม่ใช่สิ่งเดียวกัน — เรียนรู้หลักการ clean code ที่ทำให้ FiveM script ของคุณอ่านง่าย, แก้ง่าย และขยายได้
วิธีทดสอบ FiveM Script ก่อน Deploy ขึ้น Production Server
อย่า deploy script ที่ยังไม่ผ่านการทดสอบลงบน production — เรียนรู้วิธีสร้าง testing workflow สำหรับ FiveM ที่ลด downtime และป้องกัน bug จากผู้เล่นจริง