Skip to content

Tommy's Unit Numbers

Unit numbers that are drawn, not bolted on

Docs
FiveMEscrowstandaloneqbcoreesx
tUnit

tUnit

1 / 3

Escrow
$19.99

One-time purchase — lifetime access to this product, for as long as we continue to offer it.

Powered by Tebex. Instant delivery to your Cfx.re account. Refund policy.

FiveM usage

No data

No usage figures for this product yet.

Description

Text on a vehicle for FiveM — a unit number, a callsign, a department name — drawn from a single DUI texture atlas instead of built out of props. Any characters, any font, any colour, anywhere on the car, positioned with a 3D gizmo and shareable between servers.

It is the overhaul of uNumber/uNumberProps, and it spawns nothing: no attached objects, no streamed models, no per-digit arithmetic.

entities spawned, and no streamed props
0
characters per element — letters, digits and punctuation
24
text elements per vehicle model
16
dependency — tLib, and it's free
1

Will it run on your server?

  • FiveM, standalone. No framework code and nothing to detect
  • Requires tLib v1.0 or newer — free
  • No database. Nothing to import, no connection string
  • A value comes from a function you write, so ESX, QBCore, a custom MDT or nothing at all are the same amount of work
  • config.lua, config/sv_sources.lua and your own webfonts are left outside escrow

What it is not

  • Not a livery or decal system. It draws text — one quad, one string
  • Not per-client. Values resolve on the server and publish to the vehicle's state bag, so everyone reads the same car the same way
  • Not a prop pack. There is nothing to stream and nothing to spawn

One quad, not twenty props

The script this replaces spawned one real object per digit from twenty streamed .ydr props and attached each to a bone. That is why it could only ever show 0–999, why a second colour meant a second prop per digit, and why its three configured slots only took effect at exactly three digits — for one or two it ignored two thirds of the config and used hardcoded offsets.

Here a text element is a quad textured from one shared atlas and tinted at draw time. Letters are free, length is free, colour is free, and the per-digit slot arithmetic that caused most of the old script's bugs does not exist: the text is centred in its own quad, so its length no longer changes where it sits.

Positioned by eye, not by guesswork

/tunitedit puts the element on a 3D gizmo in vehicle-local space — the same gizmo tRadar and tELS use, so your admins already know the controls. Size is a centimetre slider, because a text field for a number somebody is nudging while watching the car is the wrong control.

What they position is saved per vehicle model and wins over the shipped config, so an update that touches config.lua cannot undo a layout somebody tuned in game.

Share the fiddly part

Positioning text on a vehicle is identical work for everyone who owns that model. One server publishes a layout, another imports it in one click.

An imported layout is treated as what it is — a stranger's data. The count is capped, offsets and sizes are clamped, only the fields tUnit understands are copied out, and a font the importing server does not have is kept in the record and resolved at read time, so the layout still draws and its author's intent survives.

The value is your code's business

An element either shows a literal string or names a source — a named value your server computes:

tUnit.source('callsign', function(src, vehicle)
    return exports['my-mdt']:GetCallsign(src)
end)

Sources resolve on the server when a player takes the wheel, and the resolved map goes into the vehicle's state bag. Every client renders from the bag, so nobody sees a different callsign on the same car, and a late joiner gets the current value without asking. Anything you would rather a driver typed is listed in the config instead and set from /tunit.

Honest about its limits

  • Distant text aliases. A DUI texture has no mip chain, so the distance fade is the mitigation — and a bigger atlas cell makes it worse, not better
  • 32 distinct strings on screen at once by default. Cells are keyed by content, so identical text shares one — far more than 32 vehicles in practice
  • One ytd streaming slot, pinned for the session. CreateRuntimeTxd has no destructor in FiveM, and one slot is the price of the whole feature