Zurück zum Blog
Tutorial8 Min. Lesezeit

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.

Das passende Script

Fertig für deinen Server, Updates inklusive.

Bereit loszulegen?

Hol dir die Scripts in unserem Shop, oder komm auf den Discord für Support, Updates und einen Blick auf das, was kommt.