Roblox'un varsayılan kamerası basit oyunlar için yeterli olsa da, aksiyon oyunlarında duvarlara çarpınca sarsılarak oyun zevkini bozar.
CameraType.Scriptable kullanarak RenderStepped üzerinde özel bir kamera tasarlayabilirsiniz. Yay fiziğiyle ağırlık hissi verip Spherecast ile duvar içine girmeyi engelleyerek AAA kalitesinde sonuç alınır.
1. Varsayılan Kameranın Aksiyon Oyunlarındaki Yetersizliği
Temel kamera sisteminin yol açtığı başlıca problemler:
- Ani Sarsıntılar: Duvara yaklaşınca kameranın aniden keskin biçimde sıçraması.
- Ağırlık Hissinin Yokluğu: Fiziksel eylemsizlik olmadan robotik takip.
- Karakterin Görüşü Kapatması: Karakterin ekran ortasında kalarak nişan almayı zorlaştırması.
- Scriptable Esnekliği: CFrame dönüşümlerini tamamen kodla yönetme özgürlüğü.
2. İkinci Dereceden Yay Fiziği ve Kritik Sönümleme
Sallantı olmadan doğal kamera ağırlığı elde etme:
- Kritik Sönümleme: 1.0 sönümleme oranı kameranın hedefi aşmadan durmasını sağlar.
- Kütle Hissi: Hızlanma ve zıplamalarda yumuşak kamera esnemesi.
- Bağımsız Dönüş: Fare tepkisinin anında kalması, konumun yayla takip etmesi.
- Kare Hızından Bağımsızlık: Bütün hesaplamalarda dt kullanarak akıcılığı koruma.
--!strict
local Workspace = game:GetService("Workspace")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local CameraController = {}
local camera = Workspace.CurrentCamera
local player = Players.LocalPlayer
local yaw, pitch = 0, 0
local targetDistance, currentDistance = 12, 12
local springPos, springVel = Vector3.zero, Vector3.zero
local SPHERE_RADIUS = 0.6
local RAY_PARAMS = RaycastParams.new()
RAY_PARAMS.FilterType = RaycastFilterType.Exclude
function CameraController.Init()
camera.CameraType = Enum.CameraType.Scriptable
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
RunService.RenderStepped:Connect(CameraController.Update)
end
function CameraController.Update(dt: number)
local char = player.Character
if not char or not char:FindFirstChild("Head") then return end
local head = char.Head :: BasePart
RAY_PARAMS.FilterDescendantsInstances = { char }
local focus = CFrame.new(head.Position) * CFrame.Angles(0, yaw, 0) * CFrame.Angles(pitch, 0, 0)
local force = (Vector3.new(2.2, 1.0, 0) - springPos) * 140 - (springVel * 22)
springVel += force * dt
springPos += springVel * dt
local targetPos = (focus * CFrame.new(springPos)).Position - (focus.LookVector * targetDistance)
local hit = Workspace:Spherecast(head.Position, SPHERE_RADIUS, targetPos - head.Position, RAY_PARAMS)
local adjDist = targetDistance
if hit and hit.Instance and hit.Instance.CanCollide then
adjDist = math.max(1.5, (hit.Position - head.Position).Magnitude - SPHERE_RADIUS)
end
currentDistance += (adjDist - currentDistance) * math.min(1, dt * 25)
camera.CFrame = focus * CFrame.new(springPos) * CFrame.new(0, 0, currentDistance)
end
return CameraController
3. Spherecast ile Duvar İçine Girmeyi Önleme
Kamera merceğinin katı cisimlerin içine girmesini engelleme:
- Hacimsel Tarama: Spherecast kameranın çevresinde gerçek bir 3D küre tarar.
- Güvenlik Mesafesi: Duvara temas etmeden önce kamerayı öne çekme.
- Yumuşak Geri Dönüş: Dar alandan çıkınca mesafeyi kademeli olarak açma.
- Keskin Kenar Koruması: Sivri köşelerde duvar arkasını göstermeme.
4. Dinamik Omuz Değişimi ve Nişan Alma (ADS)
Taktiksel çatışmalarda geniş görüş açısı yakalama:
- Omuz Değiştirme: Köşeleri kontrol etmek için sağ-sol omuz arası hızlı geçiş.
- Nişan Yakınlaştırması: Ateş ederken FOV açısını daraltma.
- Paralaks Düzeltmesi: Mermilerin ekranın tam merkezine gitmesini sağlama.
- Koşu Geri Çekilmesi: Depar atarken hafifçe geriye esneme.
5. Mobil Dokunmatik Hareketler ve Uyumluluk
Akıllı telefon ve oyun kollarında rahat denetim:
- İki Parmakla Yakınlaştırma: Mesafeyi parmak hareketiyle ayarlama.
- Sağ Ekran Alanı: Kamera dönüşünü hareket kolundan tamamen ayırma.
- Analog Kol Eğrileri: Hassas nişan alma için eğrisel tepki profili.
- Yerel İşlem: Bütün kamera hesaplamalarını telefonda bitirme.
Frequently Asked Questions
Neden Raycast yerine Spherecast kullanılmalı?
Raycast çizgi gibidir ve köşeleri kaçırabilir; Spherecast ise kameranın tüm hacmini korur.
Duvar yakınında kamera titremesi nasıl engellenir?
Mesafeyi anında kesmek yerine asimptotik enterpolasyonla yumuşatarak.
RenderStepped üzerinde kamera hesaplamak telefonu yavaşlatır mı?
Kare başına 0.05 ms'den az sürdüğü için 60 FPS akıcılığını asla bozmaz.