FiveM Entity Yönetimi: Ped, Araç ve Objeleri Yönetin
FiveM entity yönetiminde uzmanlaşın: Sunucunuzu stabil ve hızlı tutmak için ped'ler, araçlar ve nesnelerde spawn, sahiplik, culling ve temizleme işlemleri.
Agency Scripts
Agency Scripts Kurucusu ve Baş Geliştiricisi
FiveM'de Entity Yapısını Anlamak
FiveM platformunda bir entity, oyun dünyasında var olan herhangi bir nesnedir: araçlar, pedler, proplar, pickuplar ve hatta oyuncu karakteri. Her entity, native fonksiyonlar aracılığıyla etkileşim kurmak için kullandığınız bir tanıtıcıya (handle, bir tamsayı kimliği) sahiptir. Entity yönetimi FiveM geliştirmede en temel becerilerden biridir, çünkü neredeyse her script entity'lerle bir şekilde etkileşime girer. Kötü entity yönetimi bellek sızıntılarına, bir resource yeniden başlatıldıktan sonra kaybolmayan hayalet nesnelere, oyuncular arası desync sorunlarına ve nihayetinde sunucu kararsızlığına yol açar. Bu rehber, entity oluşturma, takip etme ve temizleme konularındaki doğru modelleri ele almaktadır.
Obje ve Prop Oluşturma
Prop spawn etmek için kullanılan birincil native CreateObject (veya CreateObjectNoOffset). Herhangi bir nesneyi spawn etmeden önce modeli istemeli ve yüklenmesini beklemelisiniz. Modeli önceden istememek, görünmez veya eksik bir entity ile sonuçlanır. Belleği boşaltmak için nesneyi oluşturduktan sonra modeli her zaman serbest bırakın.
-- client/entity_spawner.lua
local function SpawnProp(modelName, coords, rotation, isNetwork)
local model = joaat(modelName)
-- Request the model and wait for it to load
RequestModel(model)
local timeout = 0
while not HasModelLoaded(model) do
Wait(10)
timeout = timeout + 10
if timeout > 5000 then
print(('[ERROR] Model %s failed to load after 5s'):format(modelName))
return nil
end
end
local obj = CreateObject(model, coords.x, coords.y, coords.z, isNetwork, true, false)
if rotation then
SetEntityRotation(obj, rotation.x, rotation.y, rotation.z, 2, true)
end
-- Freeze the object so it does not fall through the ground
FreezeEntityPosition(obj, true)
-- Release the model from memory
SetModelAsNoLongerNeeded(model)
return obj
end
-- Usage
local chair = SpawnProp('prop_chair_01a', vector3(200.0, -800.0, 31.0), nil, false)
Araç Oluşturma
Araç spawn etme işlemi benzer bir modeli izler ancak şunu kullanır: CreateVehicle ve network sahipliği, yakıt seviyeleri ve plaka metni için ek hususlara sahiptir. Araçları mümkün olduğunda her zaman server tarafında spawn edin veya client'lardan gelen araç oluşturma isteklerini doğrulamak için server tarafı callback'leri kullanın.
-- client/vehicle_spawner.lua
local function SpawnVehicle(modelName, coords, heading)
local model = joaat(modelName)
RequestModel(model)
while not HasModelLoaded(model) do
Wait(10)
end
local vehicle = CreateVehicle(model, coords.x, coords.y, coords.z, heading, true, false)
-- Basic vehicle setup
SetVehicleOnGroundProperly(vehicle)
SetEntityAsMissionEntity(vehicle, true, true)
SetVehicleHasBeenOwnedByPlayer(vehicle, true)
SetVehicleNeedsToBeHotwired(vehicle, false)
SetVehRadioStation(vehicle, 'OFF')
-- Set fuel if using a fuel system
Entity(vehicle).state:set('fuel', 100.0, true)
SetModelAsNoLongerNeeded(model)
return vehicle
end
Entity Takibi ve Temizliği
Entity yönetiminin en kritik yönü, scriptinizin oluşturduğu her entity varlığını takip etmek ve resource durduğunda bunları temizlemektir. Düzgün bir temizlik yapılmazsa, entity yapıları oyun dünyasında yetim kalarak belleği ve render kaynaklarını boşa harcar. Tüm entity tanıtıcılarını saklamak için bir takip tablosu kullanın ve bir onResourceStop onları kaldıran handler.
-- client/entity_manager.lua
local ManagedEntities = {}
function RegisterEntity(entity, category)
if not DoesEntityExist(entity) then return end
ManagedEntities[entity] = {
category = category or 'default',
created = GetGameTimer(),
model = GetEntityModel(entity),
}
end
function UnregisterEntity(entity)
if ManagedEntities[entity] then
if DoesEntityExist(entity) then
SetEntityAsMissionEntity(entity, false, true)
DeleteEntity(entity)
end
ManagedEntities[entity] = nil
end
end
function CleanupCategory(category)
for entity, data in pairs(ManagedEntities) do
if data.category == category then
UnregisterEntity(entity)
end
end
end
function CleanupAllEntities()
for entity, _ in pairs(ManagedEntities) do
UnregisterEntity(entity)
end
ManagedEntities = {}
end
-- Critical: Clean up when resource stops
AddEventHandler('onResourceStop', function(resourceName)
if GetCurrentResourceName() ~= resourceName then return end
CleanupAllEntities()
end)
Ağ Varlık Sahipliği
FiveM ağ ortamında her entity'nin bir sahibi vardır, yani fizik ve konum simülasyonundan sorumlu olan istemcidir. Ağ sahipliği, entity hareketini ve çarpışmasını hangi oyuncunun istemcisinin kontrol ettiğini belirler. Ağ sahipliğini anlamak ve yönetmek, özellikle NPC'leri veya araçları uzaktan kontrol etmesi gereken scriptler için senkronize entity davranışı açısından kritik önem taşır.
-- server/ownership.lua
-- Request control of a networked entity
local function RequestEntityOwnership(src, netId)
local entity = NetworkGetEntityFromNetworkId(netId)
if not DoesEntityExist(entity) then return false end
-- Set the requesting player as the owner
SetEntityRoutingBucket(entity, GetPlayerRoutingBucket(src))
return true
end
-- client/ownership.lua
-- Request network control of an entity
local function TakeEntityControl(entity, timeout)
timeout = timeout or 2000
local start = GetGameTimer()
NetworkRequestControlOfEntity(entity)
while not NetworkHasControlOfEntity(entity) do
Wait(100)
NetworkRequestControlOfEntity(entity)
if GetGameTimer() - start > timeout then
return false
end
end
return true
end
-- Usage: Move an entity you need control of
local function MoveEntity(entity, targetCoords)
if TakeEntityControl(entity) then
SetEntityCoords(entity, targetCoords.x, targetCoords.y, targetCoords.z, false, false, false, false)
return true
end
print('[WARN] Could not get control of entity')
return false
end
Ped Oluşturma ve Yönetme
Ped (yaya) varlıkları NPC'ler, mağaza satıcıları, görev verenler ve ortam karakterleri için kullanılır. Düzgün yapılandırılmadıkları takdirde uzaklaşmalarına, çevreye tepki vermelerine veya oyunculara saldırmalarına neden olabilecek bir AI'ya sahip olduklarından özel işlem gerektirirler. Statik NPC'ler için her zaman AI'yı dondurun ve devre dışı bırakın.
-- client/ped_spawner.lua
local function SpawnStaticPed(modelName, coords, heading, scenario)
local model = joaat(modelName)
RequestModel(model)
while not HasModelLoaded(model) do
Wait(10)
end
local ped = CreatePed(0, model, coords.x, coords.y, coords.z - 1.0, heading, false, true)
-- Make the ped static and non-interactive with ambient AI
SetEntityAsMissionEntity(ped, true, true)
SetBlockingOfNonTemporaryEvents(ped, true)
SetPedFleeAttributes(ped, 0, false)
SetPedCombatAttributes(ped, 17, true)
SetPedDiesWhenInjured(ped, false)
SetEntityInvincible(ped, true)
FreezeEntityPosition(ped, true)
-- Play a scenario animation if specified
if scenario then
TaskStartScenarioInPlace(ped, scenario, 0, true)
end
SetModelAsNoLongerNeeded(model)
RegisterEntity(ped, 'npc')
return ped
end
-- Spawn a shop vendor
local vendor = SpawnStaticPed(
's_m_y_ammucity_01',
vector3(22.0, -1105.0, 29.8),
160.0,
'WORLD_HUMAN_STAND_IMPATIENT'
)
Entity Yönetimi İçin Performans İpuçları
- Aktif varlıkları sınırlandırın. Her entity bellek ve render döngüsü tüketir. Oyuncu yakındayken entity'leri yüklemek ve bölgeden ayrıldığında kaldırmak için streaming sistemleri kullanın.
- Nesne havuzları kullanın. Mermi kovanları veya parçacık efektleri gibi sık sık oluşturulan ve silinen entity'ler için sürekli yenilerini oluşturup silmek yerine entity handle'larını yeniden kullanın.
- Client tarafı entity'leri tercih edin. Bir entity'nin yalnızca tek bir oyuncuya görünmesi gerekiyorsa (UI prop'u veya önizleme nesnesi gibi), sunucu yükünü azaltmak için bunu non-networked olarak oluşturun.
- Her zaman SetModelAsNoLongerNeeded çağrısı yapın. Yüklenen modeller açıkça serbest bırakılana kadar bellekte kalır. Bu çağrıyı unutmak, FiveM script'lerinde bellek sızıntılarının en yaygın nedenlerinden biridir.
- İşlemlerden önce DoesEntityExist kontrolü yapın. Entity'ler oyun motoru, diğer script'ler veya desync nedeniyle silinebilir. Bir entity'yi değiştirmeye çalışmadan önce her zaman hâlâ var olduğunu doğrulayın.
- Meta veriler için entity state bag'lerini kullanın. Entity verileri için ayrı referans tabloları tutmak yerine şunu kullanın:
Entity(entity).stateözel özellikleri doğrudan entity üzerinde depolamak için.