How do I get the camera to rotate relative to the player?

In a commission, I’m attempting to add a tilt to the player when ‘ZValue’ in a module is changed. However, when the camera is oriented differently, it doesn’t fully translate to a shift in the Z-Axis. Here’s an example:


I understand it has to do with the camera shifting orientations automatically when you turn it, but I’ve attempted converting the camera to the object space–relative to the character–and changing the orientation via that, but that came out dysfunctional as well.
Here’s my code:

local character = player.Character or player.CharacterAdded:Wait()
local Val = 0

script.ZValue:GetPropertyChangedSignal("Value"):Connect(function()
	print(Val.." "..script.ZValue.Value)
	if Val ~= 0 then
		local camera = workspace.CurrentCamera
		local character = game.Players.LocalPlayer.Character or game.Players.LocalPlayer.CharacterAdded:Wait()
		local OGVal = script.ZValue.Value
		wait(2)
		local NewVal = script.ZValue.Value
		if NewVal == OGVal and script.ZValue.Value ~= 0 then
			Val = script.ZValue.Value
			local startTime = tick()
			local duration = .75
			local connection
			connection = game:GetService("RunService").RenderStepped:Connect(function()
				local elapsedTime = tick() - startTime
				local t = math.clamp(elapsedTime / duration, 0, duration)
				local rx, ry, rz = camera.CFrame:ToEulerAnglesXYZ()
				local NewCFrame = CFrame.new(camera.CFrame.Position) * CFrame.Angles(rx, ry, script.ZValue.Value)
				camera.CFrame = camera.CFrame:Lerp(NewCFrame, t * 1.333333333)
				if script.ZValue.Value ~= NewVal then
					connection:Disconnect()
				end
			end)
		end
	else
		Val = 0
		local camera = workspace.CurrentCamera
		local character = game.Players.LocalPlayer.Character or game.Players.LocalPlayer.CharacterAdded:Wait()
		local OGVal = script.ZValue.Value
		local NewVal = script.ZValue.Value
		if NewVal == OGVal and script.ZValue.Value ~= 0 then
			local startTime = tick()
			local duration = .75
			local connection
			connection = game:GetService("RunService").RenderStepped:Connect(function()
				local elapsedTime = tick() - startTime
				local t = math.clamp(elapsedTime / duration, 0, duration)
				local rx, ry, rz = camera.CFrame:ToEulerAnglesXYZ()
				local NewCFrame = CFrame.new(camera.CFrame.Position) * CFrame.Angles(rx, ry, script.ZValue.Value)
				camera.CFrame = camera.CFrame:Lerp(NewCFrame, t * 1.333333333)
				if script.ZValue.Value ~= NewVal then
					connection:Disconnect()
				end
			end)
		end
	end
end)
1 Like

This function and ToEulerAnglesYXZ() always confuse me, however, the latter function may be the appropriate one. Try using the latter instead.

2 Likes

That was actually the fix. I’m surprised I didn’t find it sooner… thank you so much!

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.