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)veDisplayRadar(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.