Bloga Geri Dön
Tutorial7 dk. okuma

FiveM HUD Geliştirme: Sade ve Hızlı Bir Oyuncu HUD'ı Tasarlayın

HTML ve JS ile yüksek performanslı bir FiveM HUD oluşturun. Can, dayanıklılık, ses, hız ve minimap katmanlarının yanı sıra inceleyebileceğiniz veya satın alabileceğiniz en iyi HUD scriptleri.

Agency Scripts

Agency Scripts Kurucusu ve Baş Geliştiricisi

Neden Özel Bir HUD Geliştirilmeli?

Varsayılan GTA V HUD, FiveM sunucularının talep ettiği karmaşık roleplay senaryoları için değil, tek oyunculu bir aksiyon oyunu için tasarlanmıştır. Özel bir HUD, vanilla GTA'da bulunmayan açlık, susuzluk, stres ve meslek durumu gibi roleplay'e özel bilgileri görüntülemenizi sağlar. İşlevselliğin ötesinde, özel bir HUD sunucunuzun görsel kimliğini belirler ve bir oyuncu oyuna girdiği andan itibaren atmosferi oluşturur. Oyuncular, varsayılan UI ögelerini çalıştıran bir sunucu ile sunucunun marka kimliğine ve temasına uyan, amaca yönelik özel bir HUD'a sahip bir sunucu arasındaki kalite farkını anında fark eder. Kendi HUD'ınızı sıfırdan oluşturmak, aynı zamanda performansın her yönünü kontrol ettiğiniz anlamına gelir ve kaplamanın minimum kaynak maliyetiyle çalışmasını sağlarken oyuncularınızın tam olarak ihtiyaç duyduğu bilgileri sunar.

NUI Kaynak Yapısı

FiveM, oyun istemcisi içinde HTML, CSS ve JavaScript render etmek için NUI (New User Interface) kullanır. HUD resource'unuzun düzgün çalışması için belirli bir klasör yapısına sahip olması gerekir. İlgili fxmanifest.lua dosyası resource meta verilerini bildirir, client.lua script, oyun verilerini NUI katmanına gönderir ve html/ klasörü web tabanlı arayüzünüzü içerir. Başlamak için minimal bir resource manifest örneği:

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'
}

The ui_page yönergesi FiveM'e NUI katmanı olarak hangi HTML dosyasının işleneceğini bildirir ve files tablosu, tarayıcının erişmesi gereken her varlığı listeler. Bu listeye bir CSS dosyası veya yazı tipi eklemeyi unutursanız, tarayıcı herhangi bir hata mesajı vermeden yüklemeyi sessizce başaramaz; bu da NUI geliştirmeye yeni başlayan geliştiriciler için yaygın bir kafa karışıklığı kaynağıdır. Sorumlulukları ayırarak kaynak yapınızı temiz tutun: düzen için HTML, stil için CSS ve mantık ile animasyonlar için JavaScript.

Oyun Verilerini Kullanıcı Arayüzüne Gönderme

İstemci tarafı Lua scripti, oyun durumunu okumaktan ve bunu düzenli aralıklarla NUI katmanına aktarmaktan sorumludur. Can, zırh ve açlık ile susuzluk gibi çatılara özgü durum değerlerini toplamanız gerekir. Temel fonksiyon şudur: SendNUIMessage(), NUI çerçevesinde çalışan JavaScript'e bir JSON payload gönderir. Güncelleme sıklığınız konusunda stratejik olun çünkü her karede veri göndermek CPU döngülerini boşa harcar, çok yavaş güncelleme yapmak ise HUD'ın gecikmeli hissettirmesine neden olur. 200-500 milisaniyelik bir tick oranı, durum çubukları için doğru dengeyi sağlar:

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)

Hız göstergesi için daha hızlı bir tick oranında çalışan ayrı bir thread'e ihtiyacınız vardır, çünkü hız hızla değişir ve oyuncular sürüş sırasında gerçek zamanlı geri bildirim bekler. Araç verileri için 50-100 milisaniyelik bir aralık iyi çalışır. Kaynak tasarrufu sağlamak için hız göstergesi thread'ini yalnızca oyuncu gerçekten bir araçtayken çalıştırın ve araçtan çıktıklarında devre dışı bırakın:

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 ve CSS Arayüzünü Geliştirme

HUD tasarımınızın görseli, oyun içinde nasıl hissettireceğini belirler. Modern FiveM HUD'ları yarı saydam arka planlar, yuvarlatılmış köşeler ve hafif animasyonlar içeren temiz, minimalist tasarımlar kullanır. Durum çubuklarınızı oyun akışını engellemeyecek şekilde sol alt köşeye yerleştirin ve oyuncu araç kullanırken hız göstergesini sağ alta koyun. Birkaç değişkeni değiştirerek tüm HUD'a kolayca tema uygulayabilmek için renklerde CSS özel özelliklerini (custom properties) kullanın. Akıcı geçişlere sahip animasyonlu ilerleme çubukları HUD'a kusursuz bir his verir:

<!-- 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>

CSS için şunu kullanın: transition akıcı doldurma animasyonları oluşturmak için çubuk genişliğinde ve uygulayın pointer-events: none oyun girdisine müdahale etmemesi için tüm HUD kapsayıcısına. Her durum çubuğu için farklı renkler, oyuncuların etiketleri okumak zorunda kalmadan hangi kaynağın azaldığını hızlıca belirlemelerine yardımcı olur. Can için kırmızı, zırh için mavi, açlık için turuncu ve susuzluk için camgöbeği, oyuncuların sezgisel olarak anladığı ve yaygın olarak benimsenen bir standarttır.

JavaScript Mesaj İşleme

JavaScript katmanı Lua istemcisinden mesajları alır ve DOM'u buna göre günceller. Gelen verideki action alanına göre yönlendirme yapan bir mesaj olay dinleyicisi kaydedin. Güncelleme mantığınızı hafif tutun çünkü Lua thread'lerinizin veri gönderme sıklığında çalışır ve JavaScript katmanındaki herhangi bir gecikme doğrudan görsel takılmalara yol açar. Başlatma sırasında öğe referanslarını önbelleğe alarak güncelleme işleyicisi içindeki DOM sorgularından kaçının:

// 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;
    }
});

Kritik durumlar için çubukta yanıp sönen bir animasyon tetikleyen ve can ya da açlık tehlikeli derecede düştüğünde oyuncunun dikkatini çeken bir CSS sınıfı ekleyin. Bu tür bir görsel geri bildirim, oyuncuların durum sayılarını sürekli izlemesine güvenmekten çok daha etkilidir ve amatör HUD'ları profesyonel olanlardan ayıran bir cila katmanı ekler.

Minimap Özelleştirme

Varsayılan GTA minimap'i işlevseldir ancak çoğu özel HUD tasarımıyla görsel olarak çelişir. FiveM, native fonksiyonlar aracılığıyla minimap'in konumu, boyutu, şekli ve yakınlaştırma düzeyi üzerinde kontrol sahibi olmanızı sağlar. Dairesel bir minimap oluşturabilir, HUD düzeninize uyacak şekilde taşıyabilir, hatta tamamen gizleyip özel bir çözümle değiştirebilirsiniz. En yaygın yaklaşım, altta yatan oyun haritası işlevselliğini olduğu gibi korurken minimap'i HUD'ınızın estetiğini tamamlayacak şekilde yeniden şekillendirmektir:

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)

Minimap'i özelleştirirken her zaman farklı ekran en boy oranlarını hesaba katın. 16:9 bir ekranda kusursuz görünen bir minimap, ultra geniş monitörlerde gerilebilir veya yanlış konumlanabilir. Varsayılan ile gerçek en boy oranı arasındaki oranı hesaplayın ve bunu genişlik bileşenlerine uygulayın. Farklı oyuncu kurulumlarında tutarlı konumlandırma sağlamak için minimap'inizi en az üç yaygın çözünürlükte (1920x1080, 2560x1440 ve 3440x1440) test edin.

Varsayılan GTA HUD Öğelerini Gizleme

Özel bir HUD oluştururken, özel kullanıcı arayüzünüzün yerini aldığı varsayılan GTA öğelerini gizlemelisiniz, aksi takdirde oyuncular yinelenen bilgiler görür. FiveM şunu sağlar: HideHudComponentThisFrame() bu amaç için native, ancak her karede çağrılmalıdır çünkü GTA, HUD bileşenlerini her tick'te yeniden etkinleştirir. Bileşen kimlikleri, aranma yıldızlarından para göstergesine ve silah çarkına kadar her şeyi kapsar. Tamamen yenilenmiş bir HUD için genellikle sağlık çubuğunu, zırh çubuğunu, para göstergesini ve araç göstergelerini gizlerken alt yazılar ve bildirim pencereleri gibi temel öğeleri görünür tutmak istersiniz. Sunucu sahiplerinin kodunuzu değiştirmeden hangi varsayılan öğelerin gizleneceğini belirleyebilmesi için yapılandırılabilir bir bileşen kimliği tablosu oluşturun. Ek olarak şunu kullanın: DisplayRadar(false) HUD'ınız kendi minimap alternatifini içeriyorsa, ancak radarı gizlemenin duraklatma menüsü algılandığında yeniden etkinleştirmediğiniz sürece duraklatma menüsü haritasını da devre dışı bıraktığını unutmayın.

En İyi Performans Uygulamaları

HUD performansı kritik öneme sahiptir çünkü HUD'ınız oyuncu oyundayken sürekli çalışır ve küçük verimsizlikler bile uzun oyun seanslarında fark edilir FPS düşüşlerine yol açabilir. En etkili optimizasyon güncelleme sıklığınızı kontrol etmektir. Açlık ve susuzluk gibi yavaş değişen durum çubukları her 500 milisaniyede bir veya saniyede bir güncellenebilirken, hız gibi hızlı değişen değerler daha sık güncelleme gerektirir. Aynı verileri tekrar tekrar göndermek yerine, yalnızca değerler gerçekten değiştiğinde NUI mesajları göndermek için koşullu render kullanın. JavaScript tarafında şunlardan kaçının: innerHTML güncellemeler için, çünkü tarayıcıyı HTML'i yeniden ayrıştırmaya zorlar; ayrıca şunu kullanın: textContent veya bunun yerine doğrudan stil özelliği değişiklikleri. Sık güncellenen öğelerdeki CSS animasyonlarını en aza indirin, çünkü tarayıcının animasyon motoru ile JavaScript güncellemeleriniz çakışarak görsel aksaklıklara neden olabilir. HUD'ınız özel yazı tipleri kullanıyorsa, yazı tipi dosyasının yüklenmesi tamamlandığında düzen kaymalarını önlemek için bunları HTML head bölümünüzde önceden yükleyin. Son olarak, FiveM'in yerleşik resmon komutunu kullanın ve HUD'ınızın kare başına ortalama 0.1ms değerinden daha az tüketmesini hedefleyin, böylece istemcide çalışan düzinelerce diğer resource için pay bırakmış olursunuz.

Eşleşen script

Sunucunuz için hazır, güncellemeler dahil.

Başlamaya Hazır mısınız?

Scriptleri mağazamızdan edinin veya destek, güncellemeler ve gelecek yeniliklere göz atmak için Discord'a katılın.