ब्लॉग पर वापस
Tutorial6 मिनट पढ़ें

FiveM कैमरा सिस्टम: कस्टम कैम, CCTV और सिनेमैटिक्स

Master FiveM कैमरा स्क्रिप्टिंग। Freecam, पुलिस के लिए CCTV, सिनेमैटिक शॉट्स और प्रैक्टिकल कोड के साथ कस्टम कैमरा UI और टॉप रिसोर्स पिक्स।

Agency Scripts

Agency Scripts के संस्थापक और प्रमुख डेवलपर

कस्टम कैमरा सिस्टम क्यों महत्वपूर्ण हैं

डिफ़ॉल्ट GTA V कैमरा सामान्य गेमप्ले के लिए अच्छा काम करता है, लेकिन रोलप्ले सर्वर और कस्टम गेम मोड अक्सर विशिष्ट कैमरा व्यवहार की आवश्यकता होती है। चरित्र निर्माण स्क्रीन को ऑर्बिट कैमरों की आवश्यकता होती है जो खिलाड़ियों को अपने चरित्र के चारों ओर घुमाने देते हैं। कटसीन्स को स्क्रिप्टेड कैमरा पथों की आवश्यकता होती है जिनमें चिकनी संक्रमण होते हैं। CCTV सिस्टम को निश्चित निगरानी दृश्य चाहिए। संपत्ति पूर्वावलोकन के लिए फ्लाईथ्रू कैमरे चाहिए। एक लचीला कैमरा सिस्टम बनाना जो इन सभी उपयोग मामलों को संभालता है आपके सर्वर की प्रस्तुति गुणवत्ता में नाटकीय सुधार करेगा। यह ट्यूटोरियल FiveM कैमरा API को गहराई से कवर करता है जिसमें वास्तविक दुनिया के उदाहरण हैं जिन्हें आप तुरंत उपयोग कर सकते हैं।

कैमरा मूल बातें

FiveM कैमरे मूल उपयोग करते हैं CreateCam और CreateCamWithParams functions। एक कैमरा एक एंटिटी है जिसमें स्थिति, रोटेशन, और फील्ड ऑफ व्यू होता है। आप कई कैमरे बना सकते हैं और उनके बीच स्विच कर सकते हैं, या एक कैमरा स्थिति से दूसरे में स्मूथली इंटरपोलेट कर सकते हैं। मुख्य अवधारणा यह है कि स्क्रिप्ट कैमरे के माध्यम से रेंडरिंग सामान्य गेमप्ले कैमरे को अक्षम कर देती है, इसलिए आपको वापस संक्रमण को सावधानी से संभालना होगा।

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

चरित्र निर्माण के लिए ऑर्बिट कैमरा

एक ऑर्बिट कैमरा एक केंद्रीय बिंदु के चारों ओर घूमता है, जिससे खिलाड़ी माउस को खींचकर दृश्य को घुमा सकता है। यह चरित्र निर्माण, कपड़ों की दुकानों, और नाई की दुकानों के लिए मानक कैमरा है। कैमरा लक्ष्य से एक निश्चित दूरी बनाए रखता है और माउस मूवमेंट को केंद्र बिंदु के चारों ओर कोणीय घुमाव में परिवर्तित करता है।

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

कैमरा इंटरपोलेशन और ट्रांजिशन

दो स्थानों के बीच स्मूथ कैमरा ट्रांजिशन कटसीन्स, प्रॉपर्टी टूर और लोडिंग स्क्रीन के लिए सिनेमाई प्रभाव बनाते हैं। FiveM प्रदान करता है SetCamActiveWithInterp जो मूल रूप से इंटरपोलेशन को संभालता है, लेकिन आप संक्रमण कर्व पर अधिक नियंत्रण के लिए कस्टम ईजिंग फ़ंक्शन भी बना सकते हैं।

-- 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 निगरानी कैमरा सिस्टम

एक CCTV सिस्टम नक्शे के चारों ओर स्थित फिक्स्ड कैमरों का उपयोग करता है जिन्हें खिलाड़ी चक्रवात कर सकते हैं। प्रत्येक कैमरे की पूर्वनिर्धारित स्थिति और घुमाव होता है, और सिस्टम सुरक्षा फुटेज की तरह दिखने के लिए पोस्ट-प्रोसेसिंग प्रभाव लागू करता है। यह आमतौर पर पुलिस स्टेशनों और व्यावसायिक इंटीरियर्स में उपयोग किया जाता है।

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

कैमरा सिस्टम सर्वोत्तम प्रथाएँ

  • काम पूरा होने पर हमेशा कैमरों को नष्ट करें। अधूरा कैमरा मेमोरी लीक होता है। हर कैमरा हैंडल को ट्रैक करें और उन्हें साफ करें onResourceStop.
  • कैमरा अनुक्रमों के दौरान नियंत्रण अक्षम करें। प्लेयर स्क्रिप्टेड कैमरा सक्रिय होने पर तब तक चल, शूट या इंटरैक्ट नहीं कर सकते जब तक कि जानबूझकर अनुमति न दी गई हो।
  • उपयुक्त FOV मानों का उपयोग करें। सामान्य गेमप्ले में 50-60 FOV का उपयोग होता है। सिनेमैटिक शॉट्स में 30-40 FOV टेलीफोटो लुक के लिए होता है। व्यापक स्थापित शॉट्स में 70-90 FOV होता है।
  • कैमरा अनुक्रमों के दौरान HUD छिपाएं। उपयोग करें DisplayHud(false) और DisplayRadar(false) सिनेमैटिक कैमरों के दौरान गेमप्ले तत्वों को हटाने के लिए।
  • विभिन्न फ्रेम दरों पर ट्रांजिशन का परीक्षण करें। कैमरा इंटरपोलेशन 30fps और 144fps पर अलग दिख सकता है। चिकनी व्यवहार सुनिश्चित करने के लिए कम-श्रेणी के हार्डवेयर पर परीक्षण करें।

शुरू करने के लिए तैयार?

हमारी शॉप से स्क्रिप्ट लें, या सपोर्ट, अपडेट और आगे आने वाली चीज़ों की झलक के लिए Discord से जुड़ें।