What do you want to achieve? Keep it simple and clear!
I would like to create a first-person camera for a vehicle that follows the orientation of the car while also allowing the player to smoothly look around. For example, if I’m looking to the left at my driver-side window, when I turn the vehicle I should still be looking directly at that window. My camera should stay in-place relative to the orientation of the vehicle.
What is the issue? Include screenshots / videos if possible!
When looking around in first person in a vehicle, the camera is constantly trying to snag back to a forward-facing position, which makes it impossible to look around. Below is an example of this.
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I was able to eliminate this ‘camera snag’ by welding a Part to the player’s face when they join, which is used as the CameraSubject when the player enters the vehicle. This also allows the player to move the camera freely inside of the vehicle. However, this comes with a new problem: The camera no longer follows the orientation of the car. Below I have linked an example of this.
This probably isn’t the most efficient method, but if you were to bind to RunService’s RenderStep (which fires every frame, hence the inefficiency), you could probably then use a couple variables to calculate the change in the Y-axis rotation (which is the side-to-side movement), and then adding that onto the camera’s CFrame.
It would probably look something like this:
local RunService = game:GetService("RunService") -- Get RunService
local camera = workspace.CurrentCamera -- Get the camera
local carBase = -- PATH TO BASE OF CAR
local _, lastRY, _ = carBase.CFrame:ToOrientation() -- Get the rotation of the car at spawn
-- Put this code somewhere that runs when the player sits in the car
local handle = RunService.RenderStepped:Connect(function(_))
local _, newRY, _ = carBase.CFrame:ToOrientation() -- Get the new rotation of the car
local diff = newRY - lastRY -- Might need to swap this
camera.CFrame *= CFrame.Angles(0,diff,0) -- Add to camera's CFrame
end
-- Put this code somewhere that runs after the player gets out of the car
handle:Disconnect() -- Stops the code above so the camera doesn't break
Put this in a LocalScript in StarterCharacterScripts, and you should be good to go.
Excuse any errors, I wrote this in Notepad++, not in Studio . Tell me if you find any.
Still freaks out, this is what my script looks like
event.OnClientEvent:Connect(function() --RemoteEvent triggers from ServerScript when I sit in VehicleSeat
head.Transparency = 1 --ignore this and the line below
head.face.Transparency = 1
workspace.CurrentCamera.CameraSubject = copy --sets CameraSubject to the welded face part
player.CameraMaxZoomDistance = 0.5
handle = RunService.RenderStepped:Connect(function(_)
local _, newRY, _ = carBase.CFrame:ToOrientation() -- Get the new rotation of the car
local diff = newRY - lastRY -- Might need to swap this
workspace.CurrentCamera.CFrame *= CFrame.Angles(0,diff,0) -- Add to camera's CFrame
local _, lastRY, _ = carBase.CFrame:ToOrientation()
end)
end)
My fault again, remove the local in the last line, that just means it doesn’t actually change the lastRY outside of that function, which means it still stays as 0 when the function starts again.
For any future readers, the aforementioned script will only work with your horizontal movement, so if you’re driving up a hill, your camera will not follow the car vertically. I modified the script to compensate for this:
local carBase = workspace.Jeep.Chassis --Change this to the base of your vehicle
local lastRX, lastRY, _ = carBase.CFrame:ToOrientation()
local RunService = game:GetService("RunService")
event.OnClientEvent:Connect(function() --I'm using a RemoteEvent to call this script whenever I sit in the VehicleSeat
handle = RunService.RenderStepped:Connect(function(_)
local newRX, newRY, _ = carBase.CFrame:ToOrientation()
local diff = newRX - lastRX
local diff2 = newRY - lastRY
workspace.CurrentCamera.CFrame *= CFrame.Angles(diff,diff2,0)
lastRX, lastRY, _ = carBase.CFrame:ToOrientation()
end)
end)
event2.OnClientEvent:Connect(function() --Using another RemoteEvent that triggers when player exits the VehicleSeat
handle:Disconnect() --Stops car camera
end)
You can also add a variable for the Z axis of the camera, but it makes driving the car quite disorienting:
Replace the _ on line 7 with newRZ
Replace the 0 on line 10 with newRZ
Please tell me if this doesn’t work, I removed some parts of my actual script that weren’t relevant but I could have deleted something important in the process
Just a quick addition, you can replace the first underscore in local _, lastRY, _ with local lastRX, lastRY, _ instead of giving it a completely seperate line. An underscore just tells the script that you won’t be using that variable.