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.