Bloga Geri Dön
Tutorial5 dk. okuma

FiveM Kamera Sistemi: Özel Kameralar, CCTV ve Sinematikler

FiveM kamera script'lerinde uzmanlaşın: Pratik kodlar ve en iyi kaynak önerileriyle freecam, polisler için CCTV, sinematik çekimler ve özel kamera arayüzleri.

Agency Scripts

Agency Scripts Kurucusu ve Baş Geliştiricisi

Özel Kamera Sistemleri Neden Önemlidir?

Varsayılan GTA V kamerası genel oynanış için iyi çalışır ancak roleplay sunucuları ve özel oyun modları genellikle özel kamera davranışlarına ihtiyaç duyar. Karakter oluşturma ekranları, oyuncuların karakterleri etrafında dönmesine olanak tanıyan yörünge kameraları (orbit cameras) gerektirir. Ara sahneler, yumuşak geçişlere sahip scriptli kamera yollarına ihtiyaç duyar. CCTV sistemleri sabit gözetleme açıları gerektirir. Mülk önizlemeleri ise serbest uçuş kameralarına (flythrough) ihtiyaç duyar. Tüm bu kullanım durumlarını yöneten esnek bir kamera sistemi oluşturmak, sunucunuzun sunum kalitesini önemli ölçüde artıracaktır. Bu rehber, hemen kullanabileceğiniz gerçek dünya örnekleriyle FiveM kamera API'sini derinlemesine ele almaktadır.

Kamera Temelleri

FiveM kameraları şu native fonksiyonunu kullanır: CreateCam ve CreateCamWithParams functions. Kamera; konum, rotasyon ve görüş alanına sahip bir entity'dir. Birden fazla kamera oluşturabilir ve bunlar arasında geçiş yapabilir veya bir kamera konumundan diğerine yumuşak bir geçiş sağlayabilirsiniz. Buradaki temel kavram, bir script kamerası üzerinden render almanın normal oyun kamerasını devre dışı bırakmasıdır, bu nedenle geri dönüş geçişini dikkatle yönetmeniz gerekir.

-- client/camera_core.lua
local CameraSystem = {
    activeCam = nil,
    isActive = false,
}

function CameraSystem.Create(coords, rot, fov)
    local cam = CreateCamWithParams(
        'DEFAULT_SCRIPTED_CAMERA',
        coords.x, coords.y, coords.z,
        rot.x, rot.y, rot.z,
        fov or 60.0,
        false, 0
    )
    return cam
end

function CameraSystem.Activate(cam, transitionTime)
    transitionTime = transitionTime or 1000

    SetCamActive(cam, true)
    RenderScriptCams(true, true, transitionTime, true, false)

    CameraSystem.activeCam = cam
    CameraSystem.isActive = true
end

function CameraSystem.Deactivate(transitionTime)
    transitionTime = transitionTime or 1000

    RenderScriptCams(false, true, transitionTime, true, false)

    if CameraSystem.activeCam then
        SetCamActive(CameraSystem.activeCam, false)
        DestroyCam(CameraSystem.activeCam, false)
        CameraSystem.activeCam = nil
    end

    CameraSystem.isActive = false
end

-- Clean up on resource stop
AddEventHandler('onResourceStop', function(resourceName)
    if GetCurrentResourceName() ~= resourceName then return end
    if CameraSystem.isActive then
        CameraSystem.Deactivate(0)
    end
end)

Karakter Oluşturma için Orbit Kamera

Bir yörünge kamerası merkezi bir noktanın etrafında döner ve oyuncunun fareyi sürükleyerek görünümü döndürmesine olanak tanır. Bu, karakter oluşturma, giyim mağazaları ve berberler için standart kameradır. Kamera, hedefle arasındaki mesafeyi sabit tutar ve fare hareketini merkez noktası etrafında açısal dönüşe çevirir.

-- client/orbit_camera.lua
local OrbitCam = {
    active = false,
    cam = nil,
    target = nil,
    distance = 2.0,
    angleH = 0.0,
    angleV = 20.0,
    minV = -30.0,
    maxV = 60.0,
    sensitivity = 0.3,
    fov = 45.0,
}

function OrbitCam.Start(targetEntity, distance, height)
    OrbitCam.target = targetEntity
    OrbitCam.distance = distance or 2.0
    OrbitCam.angleH = GetEntityHeading(targetEntity) + 180.0
    OrbitCam.angleV = 20.0

    local targetCoords = GetEntityCoords(targetEntity)
    local camPos = OrbitCam.CalculatePosition(targetCoords)

    OrbitCam.cam = CreateCamWithParams(
        'DEFAULT_SCRIPTED_CAMERA',
        camPos.x, camPos.y, camPos.z,
        0.0, 0.0, 0.0,
        OrbitCam.fov, false, 0
    )

    PointCamAtCoord(OrbitCam.cam, targetCoords.x, targetCoords.y, targetCoords.z + 0.5)
    SetCamActive(OrbitCam.cam, true)
    RenderScriptCams(true, true, 800, true, false)

    OrbitCam.active = true
    OrbitCam.UpdateLoop()
end

function OrbitCam.CalculatePosition(center)
    local hRad = math.rad(OrbitCam.angleH)
    local vRad = math.rad(OrbitCam.angleV)

    local x = center.x + OrbitCam.distance * math.cos(vRad) * math.sin(hRad)
    local y = center.y + OrbitCam.distance * math.cos(vRad) * math.cos(hRad)
    local z = center.z + 0.5 + OrbitCam.distance * math.sin(vRad)

    return vector3(x, y, z)
end

function OrbitCam.UpdateLoop()
    CreateThread(function()
        while OrbitCam.active do
            DisableAllControlActions(0)
            EnableControlAction(0, 1, true)   -- Mouse X
            EnableControlAction(0, 2, true)   -- Mouse Y
            EnableControlAction(0, 241, true)  -- Scroll Up
            EnableControlAction(0, 242, true)  -- Scroll Down

            -- Mouse rotation
            local mouseX = GetDisabledControlNormal(0, 1) * OrbitCam.sensitivity * 8.0
            local mouseY = GetDisabledControlNormal(0, 2) * OrbitCam.sensitivity * 8.0

            OrbitCam.angleH = OrbitCam.angleH - mouseX
            OrbitCam.angleV = math.max(OrbitCam.minV,
                math.min(OrbitCam.maxV, OrbitCam.angleV + mouseY))

            -- Scroll zoom
            if IsDisabledControlPressed(0, 241) then
                OrbitCam.distance = math.max(0.5, OrbitCam.distance - 0.1)
            elseif IsDisabledControlPressed(0, 242) then
                OrbitCam.distance = math.min(5.0, OrbitCam.distance + 0.1)
            end

            local targetCoords = GetEntityCoords(OrbitCam.target)
            local camPos = OrbitCam.CalculatePosition(targetCoords)

            SetCamCoord(OrbitCam.cam, camPos.x, camPos.y, camPos.z)
            PointCamAtCoord(OrbitCam.cam, targetCoords.x, targetCoords.y, targetCoords.z + 0.5)

            Wait(0)
        end
    end)
end

function OrbitCam.Stop()
    OrbitCam.active = false
    RenderScriptCams(false, true, 800, true, false)

    if OrbitCam.cam then
        SetCamActive(OrbitCam.cam, false)
        DestroyCam(OrbitCam.cam, false)
        OrbitCam.cam = nil
    end
end

Kamera İnterpolasyonu ve Geçişleri

İki konum arasındaki akıcı kamera geçişleri, ara sahneler, mülk turları ve yükleme ekranları için sinematik efektler oluşturur. FiveM şunları sunar: SetCamActiveWithInterp interpolasyonu yerel olarak işler, ancak geçiş eğrisi üzerinde daha fazla kontrol sahibi olmak için özel easing fonksiyonları da oluşturabilirsiniz.

-- client/camera_transition.lua
local function TransitionCamera(fromPos, fromRot, toPos, toRot, duration, fov)
    fov = fov or 50.0

    local camFrom = CreateCamWithParams('DEFAULT_SCRIPTED_CAMERA',
        fromPos.x, fromPos.y, fromPos.z,
        fromRot.x, fromRot.y, fromRot.z,
        fov, false, 0)

    local camTo = CreateCamWithParams('DEFAULT_SCRIPTED_CAMERA',
        toPos.x, toPos.y, toPos.z,
        toRot.x, toRot.y, toRot.z,
        fov, false, 0)

    SetCamActive(camFrom, true)
    RenderScriptCams(true, false, 0, true, false)

    -- Interpolate from first camera to second
    SetCamActiveWithInterp(camTo, camFrom, duration, 1, 1)

    Wait(duration)

    -- Clean up the first camera
    DestroyCam(camFrom, false)

    return camTo
end

-- Usage: Flythrough preview of a property
local function PropertyPreview(waypoints, duration)
    local perSegment = duration / (#waypoints - 1)
    local currentCam = nil

    for i = 1, #waypoints - 1 do
        local wp = waypoints[i]
        local nextWp = waypoints[i + 1]

        currentCam = TransitionCamera(
            wp.pos, wp.rot,
            nextWp.pos, nextWp.rot,
            perSegment, wp.fov or 60.0
        )
    end

    -- Return to gameplay camera
    Wait(500)
    RenderScriptCams(false, true, 1000, true, false)
    if currentCam then DestroyCam(currentCam, false) end
end

CCTV Güvenlik Kamerası Sistemi

Bir CCTV sistemi, harita genelinde oyuncuların sırayla geçiş yapabileceği sabit kameralar kullanır. Her kameranın önceden tanımlanmış bir konumu ve rotasyonu vardır; sistem güvenlik kamerası görüntüsü hissi vermek için bir post-processing efekti uygular. Bu özellik genellikle polis karakollarında ve işletme iç mekanlarında kullanılır.

-- client/cctv.lua
local CCTV = {
    cameras = {},
    currentIndex = 0,
    activeCam = nil,
    active = false,
}

function CCTV.AddCamera(name, coords, rot, fov)
    table.insert(CCTV.cameras, {
        name = name,
        coords = coords,
        rot = rot,
        fov = fov or 60.0,
    })
end

function CCTV.Start(startIndex)
    CCTV.currentIndex = startIndex or 1
    CCTV.active = true
    CCTV.SwitchTo(CCTV.currentIndex)

    CreateThread(function()
        while CCTV.active do
            -- Apply security camera filter
            SetTimecycleModifier('CAMERA_secuirity')
            SetTimecycleModifierStrength(1.0)

            DisableAllControlActions(0)
            EnableControlAction(0, 174, true) -- Left Arrow
            EnableControlAction(0, 175, true) -- Right Arrow
            EnableControlAction(0, 202, true) -- Escape

            -- Cycle cameras
            if IsDisabledControlJustPressed(0, 175) then
                local next = CCTV.currentIndex + 1
                if next > #CCTV.cameras then next = 1 end
                CCTV.SwitchTo(next)
            elseif IsDisabledControlJustPressed(0, 174) then
                local prev = CCTV.currentIndex - 1
                if prev < 1 then prev = #CCTV.cameras end
                CCTV.SwitchTo(prev)
            elseif IsDisabledControlJustPressed(0, 202) then
                CCTV.Stop()
            end

            Wait(0)
        end
    end)
end

function CCTV.SwitchTo(index)
    local data = CCTV.cameras[index]
    if not data then return end

    local newCam = CreateCamWithParams('DEFAULT_SCRIPTED_CAMERA',
        data.coords.x, data.coords.y, data.coords.z,
        data.rot.x, data.rot.y, data.rot.z,
        data.fov, false, 0)

    if CCTV.activeCam then
        SetCamActiveWithInterp(newCam, CCTV.activeCam, 500, 1, 1)
        Wait(500)
        DestroyCam(CCTV.activeCam, false)
    else
        SetCamActive(newCam, true)
        RenderScriptCams(true, true, 500, true, false)
    end

    CCTV.activeCam = newCam
    CCTV.currentIndex = index
end

function CCTV.Stop()
    CCTV.active = false
    ClearTimecycleModifier()
    RenderScriptCams(false, true, 800, true, false)

    if CCTV.activeCam then
        DestroyCam(CCTV.activeCam, false)
        CCTV.activeCam = nil
    end
end

Kamera Sistemi En İyi Uygulamaları

  • İşiniz bittiğinde kameraları her zaman silin. Yok edilmeyen kameralar bellek sızıntısına yol açar. Her kamera tanıtıcısını takip edin ve şurada temizleyin: onResourceStop.
  • Kamera sekansları sırasında kontrolleri devre dışı bırakın. Özel olarak izin verilmediği sürece, scriptli bir kamera etkinken oyuncular yürüyememeli, ateş edememeli veya etkileşime girememelidir.
  • Uygun FOV değerleri kullanın. Normal oynanış 50-60 FOV kullanır. Sinematik çekimler telefoto görünümü için 30-40 FOV kullanır. Geniş açılı genel çekimler 70-90 FOV kullanır.
  • Kamera sekansları sırasında HUD'ı gizleyin. Kullanın DisplayHud(false) ve DisplayRadar(false) sinematik kameralar sırasında oynanış öğelerini kaldırmak için.
  • Geçişleri farklı kare hızlarında test edin. Kamera interpolasyonu 30fps ile 144fps arasında farklı görünebilir. Sorunsuz bir davranış sağlamak için düşük donanımlarda test edin.

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.