PolyZone
The zone library that taught FiveM to think in shapes: polygons, boxes, circles and entity zones with enter and exit events.
Before PolyZone, a 'zone' in a FiveM script was a distance check against a coordinate. PolyZone introduced real shapes — arbitrary polygons drawn around a car park, boxes around a doorway, circles around a landmark — with cheap point-in-shape tests and proper enter/exit callbacks. Half the free scripts in circulation still depend on it, and the gang territories and job areas you see painted onto server maps are usually PolyZone shapes underneath.
At a glance
| Maintainer | mkafrin |
| Latest release | v2.6.2 · 2025-01-05 |
| Last code change | 2025-03-09 |
| Licence | MIT |
| Written in | Lua |
| GitHub stars | 249 |
| Status | Active |
Figures read from the repository on 2026-09-22.
Why servers run it
- Arbitrary polygons, not just radii. A harbour is not a circle and a gang block is not a square.
- Combo zones let you treat several shapes as one area with a single enter event.
- Entity zones follow a vehicle or a ped, which is how 'inside this truck' becomes a condition.
- A built-in drawing mode lets you walk the outline in game and print the coordinates.
Installing PolyZone
1. Drop it in and start it first
PolyZone is a library. ensure PolyZone before any resource that requires it.
2. Add the client import
Resources using it need
client_script '@PolyZone/client.lua'plus the specific shape files they use — BoxZone.lua, CircleZone.lua, ComboZone.lua, EntityZone.lua.3. Draw your zone in game
Start the resource, use the built-in pzcreate commands to walk the outline, and copy the printed table straight into your config.
4. Check whether you need it
New code should usually use ox_lib's zones module instead. Install PolyZone because an existing script asks for it.
Working examples
fxmanifest.lua — importing the shapes you use
client_scripts {
'@PolyZone/client.lua',
'@PolyZone/BoxZone.lua',
'@PolyZone/CircleZone.lua',
'@PolyZone/ComboZone.lua',
'client.lua',
}A gang territory as a real polygon
local territory = PolyZone:Create({
vector2(-1000.0, -1500.0),
vector2( -900.0, -1450.0),
vector2( -880.0, -1600.0),
vector2( -980.0, -1650.0),
}, {
name = 'ballas_block',
minZ = 10.0,
maxZ = 40.0,
debugPoly = false, -- true draws the outline in game
})
territory:onPlayerInOut(function(isPointInside)
if isPointInside then
TriggerEvent('territory:enter', 'ballas_block')
else
TriggerEvent('territory:exit', 'ballas_block')
end
end)A box around a doorway
local door = BoxZone:Create(
vector3(441.3, -981.7, 30.7), 2.0, 1.5, {
name = 'mrpd_front',
heading = 0,
minZ = 29.7,
maxZ = 33.7,
})What goes wrong
minZ and maxZ are not optional in practice. A polygon with no height bounds also covers the tunnel underneath it and the roof above it.
debugPoly costs frames. It draws every edge every frame. It is a placement tool, not a setting to leave on.
Only import the shape files you use. Importing all of them into every resource adds load time for no reason.
PolyZone is client side. A zone check on the server has to be an event from the client, which means it can be lied about — validate anything that matters.
PolyZone — questions people ask
Is PolyZone still needed in 2026?
How do I draw a PolyZone?
Does a zone show on the minimap?
Runs alongside
The shared library half the modern FiveM ecosystem depends on: menus, notifications, progress bars, zones, callbacks and a cache.
The third-eye interaction system most modern scripts target: look at a thing, get a menu, click an option.
QBCore's third-eye targeting system, and the export signature a very large number of existing scripts are written against.