FiveM-HUD-Entwicklung: Gestalte ein übersichtliches, schnelles Spieler-HUD
Erstelle ein performantes FiveM-HUD mit HTML und JS. Anzeigen für Gesundheit, Ausdauer, Sprache, Tempo und Minikarte sowie empfehlenswerte HUD-Scripts.
Agency Scripts
Gründer und leitender Entwickler bei Agency Scripts
Warum du einen eigenen HUD erstellen solltest
Das standardmäßige GTA V-HUD wurde für ein Einzelspieler-Actionspiel entwickelt, nicht für die komplexen Roleplay-Szenarien, die FiveM-Server erfordern. Mit einem benutzerdefinierten HUD kannst du Roleplay-spezifische Informationen wie Hunger, Durst, Stress und Jobstatus anzeigen, die es im normalen GTA schlichtweg nicht gibt. Neben der Funktionalität prägt ein benutzerdefiniertes HUD die visuelle Identität deines Servers und gibt vom Moment des Spawnens an den Ton vor. Spieler bemerken sofort den Qualitätsunterschied zwischen einem Server mit standardmäßigen UI-Elementen und einem mit einem ausgefeilten, speziell entwickelten HUD, das zum Branding und Thema des Servers passt. Wenn du dein eigenes HUD von Grund auf entwickelst, hast du außerdem die volle Kontrolle über die Performance. So stellst du sicher, dass das Overlay möglichst wenig Ressourcen verbraucht und genau die Informationen bereitstellt, die deine Spieler benötigen.
NUI-Ressourcenstruktur
FiveM verwendet NUI (New User Interface), um HTML, CSS und JavaScript im Spielclient darzustellen. Damit deine HUD-Ressource korrekt funktioniert, braucht sie eine bestimmte Ordnerstruktur. Die fxmanifest.lua Datei enthält die Metadaten der Ressource, das client.lua Skript sendet Spieldaten an die NUI-Ebene und der html/ Ordner enthält deine webbasierte Benutzeroberfläche. Hier ist ein minimales Ressourcenmanifest für den Einstieg:
fx_version 'cerulean'
game 'gta5'
description 'Custom HUD'
author 'YourName'
version '1.0.0'
ui_page 'html/index.html'
client_script 'client.lua'
files {
'html/index.html',
'html/style.css',
'html/script.js',
'html/fonts/*.woff2'
}
Die ui_page Die Direktive teilt FiveM mit, welche HTML-Datei als NUI-Overlay dargestellt werden soll, und die files Tabelle führt alle Assets auf, auf die der Browser zugreifen muss. Wenn du vergisst, eine CSS-Datei oder Schriftart in diese Liste aufzunehmen, kann der Browser sie nicht laden, ohne eine Fehlermeldung anzuzeigen. Das sorgt bei Entwicklern, die neu in der NUI-Entwicklung sind, häufig für Verwirrung. Halte deine Ressourcenstruktur übersichtlich und trenne die Zuständigkeiten: HTML für das Layout, CSS für das Styling und JavaScript für Logik und Animationen.
Spieldaten an die UI senden
Das clientseitige Lua-Skript liest den Spielstatus aus und sendet ihn regelmäßig an die NUI-Ebene. Du musst Gesundheit, Rüstung und framework-spezifische Statuswerte wie Hunger und Durst erfassen. Die zentrale Funktion ist SendNUIMessage() , die eine JSON-Payload an das im NUI-Frame laufende JavaScript sendet. Wähle die Aktualisierungsrate mit Bedacht: Wenn du die Daten bei jedem Frame sendest, verschwendest du CPU-Zyklen. Aktualisierst du sie zu selten, wirkt das HUD verzögert. Eine Tick-Rate von 200-500 Millisekunden bietet bei Statusleisten eine gute Balance:
CreateThread(function()
while true do
local ped = PlayerPedId()
local health = GetEntityHealth(ped) - 100 -- GTA health starts at 100
local maxHealth = GetEntityMaxHealth(ped) - 100
local armor = GetPedArmour(ped)
-- Framework-specific data (QBCore example)
local playerData = QBCore.Functions.GetPlayerData()
local hunger = playerData.metadata['hunger'] or 100
local thirst = playerData.metadata['thirst'] or 100
local stress = playerData.metadata['stress'] or 0
SendNUIMessage({
action = 'updateStatus',
health = math.floor((health / maxHealth) * 100),
armor = armor,
hunger = math.floor(hunger),
thirst = math.floor(thirst),
stress = math.floor(stress)
})
Wait(300)
end
end)
Für den Tachometer brauchst du einen separaten Thread mit einer höheren Tick-Rate, da sich die Geschwindigkeit schnell ändert und Spieler beim Fahren Echtzeit-Feedback erwarten. Für Fahrzeugdaten eignet sich ein Intervall von 50-100 Millisekunden. Starte den Tachometer-Thread nur, wenn sich der Spieler tatsächlich in einem Fahrzeug befindet, um Ressourcen zu sparen, und beende ihn beim Aussteigen:
CreateThread(function()
while true do
local ped = PlayerPedId()
if IsPedInAnyVehicle(ped, false) then
local veh = GetVehiclePedIsIn(ped, false)
local speed = GetEntitySpeed(veh) * 3.6 -- Convert to km/h
local rpm = GetVehicleCurrentRpm(veh)
local gear = GetVehicleCurrentGear(veh)
local fuel = GetVehicleFuelLevel(veh)
SendNUIMessage({
action = 'updateVehicle',
speed = math.floor(speed),
rpm = rpm,
gear = gear,
fuel = math.floor(fuel)
})
Wait(50)
else
SendNUIMessage({ action = 'hideVehicle' })
Wait(500)
end
end
end)
HTML- und CSS-Oberfläche erstellen
Das visuelle Design deines HUDs bestimmt, wie es sich im Spiel anfühlt. Moderne FiveM-HUDs setzen auf klare, minimalistische Designs mit halbtransparenten Hintergründen, abgerundeten Ecken und dezenten Animationen. Platziere deine Statusleisten unten links, wo sie das Spielgeschehen nicht verdecken, und den Tachometer beim Fahren unten rechts. Nutze CSS Custom Properties für Farben, damit du das gesamte HUD ganz einfach mit wenigen Variablen anpassen kannst. Animierte Fortschrittsleisten mit weichen Übergängen sorgen für ein ausgefeiltes Erscheinungsbild:
<!-- html/index.html -->
<div id="hud-container">
<div class="status-bars">
<div class="bar-wrapper">
<i class="icon health-icon"></i>
<div class="bar">
<div class="bar-fill health-fill" id="health-bar"></div>
</div>
</div>
<div class="bar-wrapper">
<i class="icon armor-icon"></i>
<div class="bar">
<div class="bar-fill armor-fill" id="armor-bar"></div>
</div>
</div>
<div class="bar-wrapper">
<i class="icon hunger-icon"></i>
<div class="bar">
<div class="bar-fill hunger-fill" id="hunger-bar"></div>
</div>
</div>
<div class="bar-wrapper">
<i class="icon thirst-icon"></i>
<div class="bar">
<div class="bar-fill thirst-fill" id="thirst-bar"></div>
</div>
</div>
</div>
<div class="speedometer" id="speedometer" style="display:none">
<div class="speed-value" id="speed-value">0</div>
<div class="speed-unit">KM/H</div>
<div class="fuel-bar">
<div class="fuel-fill" id="fuel-bar"></div>
</div>
</div>
</div>
Verwende im CSS transition für die Breite der Leiste, um weiche Füllanimationen zu erzeugen, und wende pointer-events: none auf den gesamten HUD-Container an, damit er die Spieleingabe nicht beeinträchtigt. Unterschiedliche Farben für die einzelnen Statusleisten helfen Spielern, schnell zu erkennen, welcher Wert niedrig ist, ohne Beschriftungen lesen zu müssen. Rot für Gesundheit, Blau für Rüstung, Orange für Hunger und Cyan für Durst sind eine weit verbreitete Konvention, die Spieler intuitiv verstehen.
JavaScript-Nachrichten verarbeiten
Die JavaScript-Ebene empfängt Nachrichten vom Lua-Client und aktualisiert entsprechend das DOM. Registriere einen Event Listener für Nachrichten, der anhand des Action-Felds in der Payload entscheidet, welche Aktion ausgeführt wird. Halte deine Aktualisierungslogik schlank, da sie mit der Frequenz deiner Lua-Threads ausgeführt wird. Verzögerungen in der JavaScript-Ebene führen direkt zu sichtbarem Ruckeln. Vermeide DOM-Abfragen im Update-Handler, indem du Elementreferenzen bei der Initialisierung zwischenspeicherst:
// html/script.js
const elements = {
healthBar: document.getElementById('health-bar'),
armorBar: document.getElementById('armor-bar'),
hungerBar: document.getElementById('hunger-bar'),
thirstBar: document.getElementById('thirst-bar'),
speedometer: document.getElementById('speedometer'),
speedValue: document.getElementById('speed-value'),
fuelBar: document.getElementById('fuel-bar')
};
window.addEventListener('message', (event) => {
const data = event.data;
switch (data.action) {
case 'updateStatus':
elements.healthBar.style.width = data.health + '%';
elements.armorBar.style.width = data.armor + '%';
elements.hungerBar.style.width = data.hunger + '%';
elements.thirstBar.style.width = data.thirst + '%';
// Color shift when low
if (data.health < 25) {
elements.healthBar.classList.add('critical');
} else {
elements.healthBar.classList.remove('critical');
}
break;
case 'updateVehicle':
elements.speedometer.style.display = 'flex';
elements.speedValue.textContent = data.speed;
elements.fuelBar.style.width = data.fuel + '%';
break;
case 'hideVehicle':
elements.speedometer.style.display = 'none';
break;
}
});
Füge eine CSS-Klasse für kritische Zustände hinzu, die eine pulsierende Animation der Leiste auslöst und die Aufmerksamkeit des Spielers auf sich zieht, wenn Gesundheit oder Hunger gefährlich niedrig sind. Dieses visuelle Feedback ist wesentlich effektiver, als von Spielern zu erwarten, dass sie ihre Statuswerte ständig im Blick behalten. Außerdem sorgt es für den letzten Schliff, der Amateur-HUDs von professionellen unterscheidet.
Minimap anpassen
Die standardmäßige GTA-Minimap ist funktional, passt optisch aber oft nicht zu benutzerdefinierten HUD-Designs. Mit nativen Funktionen kannst du Position, Größe, Form und Zoomstufe der Minimap in FiveM anpassen. Du kannst eine runde Minimap erstellen, sie passend zu deinem HUD-Layout verschieben oder sie ganz ausblenden und durch eine eigene Lösung ersetzen. Am häufigsten wird die Form der Minimap so angepasst, dass sie zum Stil des HUDs passt, während die zugrunde liegende Kartenfunktion des Spiels erhalten bleibt:
CreateThread(function()
-- Wait for map to load
Wait(500)
-- Set minimap shape and position
local minimapHandle = RequestScaleformMovie('MINIMAP')
SetMinimapClipType(1) -- 0 = rectangle, 1 = circle
-- Adjust minimap position and size
local defaultAspect = 1920 / 1080
local resX, resY = GetActiveScreenResolution()
local aspect = resX / resY
local ratio = defaultAspect / aspect
SetMinimapComponentPosition('minimap', 'L', 'B',
0.0, -0.032, 0.145 * ratio, 0.210)
SetMinimapComponentPosition('minimap_mask', 'L', 'B',
0.0, 0.032, 0.128 * ratio, 0.300)
SetMinimapComponentPosition('minimap_blur', 'L', 'B',
-0.01, -0.032, 0.272 * ratio, 0.420)
-- Hide default health and armor bars
local minimap = RequestScaleformMovie('MINIMAP')
while not HasScaleformMovieLoaded(minimap) do Wait(0) end
while true do
-- Disable default HUD components
HideHudComponentThisFrame(6) -- Vehicle name
HideHudComponentThisFrame(7) -- Area name
HideHudComponentThisFrame(8) -- Vehicle class
HideHudComponentThisFrame(9) -- Street name
Wait(0)
end
end)
Berücksichtige beim Anpassen der Minimap immer verschiedene Bildschirmseitenverhältnisse. Eine Minimap, die auf einem 16:9-Display perfekt aussieht, kann auf Ultrawide-Monitoren verzerrt oder falsch positioniert sein. Berechne das Verhältnis zwischen dem standardmäßigen und dem tatsächlichen Seitenverhältnis und wende es auf die Breitenwerte an. Teste deine Minimap auf mindestens drei gängigen Auflösungen (1920x1080, 2560x1440 und 3440x1440), um eine konsistente Positionierung auf den verschiedenen Setups deiner Spieler sicherzustellen.
Standardmäßige GTA-HUD-Elemente ausblenden
Wenn du ein benutzerdefiniertes HUD entwickelst, musst du die standardmäßigen GTA-Elemente ausblenden, die durch deine eigene UI ersetzt werden. Andernfalls sehen Spieler Informationen doppelt. FiveM stellt dafür die native Funktion HideHudComponentThisFrame() bereit. Sie muss jedoch bei jedem Frame aufgerufen werden, da GTA die HUD-Komponenten bei jedem Tick wieder aktiviert. Die Komponenten-IDs umfassen alles, von den Fahndungssternen über die Bargeldanzeige bis zum Waffenrad. Bei einem vollständigen Ersatz-HUD blendest du normalerweise Gesundheits- und Rüstungsleisten, Bargeldanzeige und Fahrzeuganzeigen aus, während wichtige Elemente wie Untertitel und Benachrichtigungs-Popups sichtbar bleiben. Erstelle eine konfigurierbare Tabelle mit Komponenten-IDs, damit Serverbesitzer festlegen können, welche standardmäßigen Elemente ausgeblendet werden, ohne deinen Code ändern zu müssen. Verwende außerdem DisplayRadar(false) wenn dein HUD eine eigene Minimap enthält. Beachte dabei, dass das Ausblenden des Radars auch die Karte im Pausenmenü deaktiviert, sofern du sie beim Erkennen des Pausenmenüs nicht wieder aktivierst.
Best Practices für die Performance
Die Performance des HUDs ist entscheidend, da es während des gesamten Spiels dauerhaft läuft. Selbst kleine Ineffizienzen können sich bei längeren Spielsitzungen zu spürbaren Framerate-Einbrüchen summieren. Die wirkungsvollste Optimierung ist, die Aktualisierungsfrequenz zu steuern. Langsam veränderliche Statusleisten wie Hunger und Durst können alle 500 Millisekunden oder sogar jede Sekunde aktualisiert werden, während sich schnell ändernde Werte wie die Geschwindigkeit häufigere Updates benötigen. Nutze bedingtes Rendering und sende NUI-Nachrichten nur, wenn sich Werte tatsächlich ändern, statt wiederholt dieselben Daten zu übertragen. Vermeide auf der JavaScript-Seite innerHTML bei Aktualisierungen, da der Browser dadurch HTML erneut parsen muss, und verwende textContent oder ändere direkt die Stileigenschaften. Verwende möglichst wenige CSS-Animationen für Elemente, die häufig aktualisiert werden, da sich die Animations-Engine des Browsers und deine JavaScript-Aktualisierungen in die Quere kommen und visuelle Fehler verursachen können. Wenn dein HUD benutzerdefinierte Schriftarten verwendet, lade sie im HTML-Head vorab, damit es beim Laden der Schriftdatei nicht zu Layoutverschiebungen kommt. Profiliere deine Ressource abschließend mit dem integrierten resmon Befehl von FiveM und strebe an, dass dein HUD im Durchschnitt weniger als 0.1ms pro Frame verbraucht. So bleibt genug Spielraum für die Dutzenden anderen Ressourcen, die auf dem Client laufen.