Bloga Geri Dön
Tutorial5 dk. okuma

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.

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.