How do I fix my camera CFrame rotation?

So I have a freecam script and I have a part that makes the camera rotate when a player is holding down right mouse button:

local mouseDelta = UserInputService:GetMouseDelta()
local slowness = 200
local x, y = -mouseDelta.X/slowness, -mouseDelta.Y/slowness
camera.CFrame *= CFrame.Angles(y,x,0) -- rotate

But it doesnt seem to rotate the cframe quite properly. It rotates it along the X and Y axes but theres also Z axis rotation which I dont want to have; it looks like this:
1821.wmv (3.0 MB)
This is how its supposed to look like:
1822.wmv (3.3 MB)

1 Like

The easiest solution would be just using CFrame.FromEulerAnglesYXZ(y,x,0) rather than CFrame.Angles
This applies the angles in a more sensical order in terms of what most people need

When a CFrame is rotated along the X axis first, it also rotates all of the other axes away from the downward position and causes mega issues like the one you’re experiencing if not handled correctly

Demonstration:
image
image
When the y axis is rotated first it should bypass your issue

3 Likes

I’ve tried that and it does not change anything. The rotation just looks the same (check first video).
camera.CFrame *= CFrame.fromEulerAnglesYXZ(y,x,0)
Although, very good explanation but I dont understand whats wrong in my code.

…Ah, I see you are right. My best guess now is to somehow rotate the camera’s cframe relative to global space?

I’m starting to see your troubles after testing it out myself (hi from your previous topic lol). Maybe you should have gave out your code so it would be easier next time.

Anyways luckily it has been done before from documentation it GetMouseDelta for an example camera script
I have noted that this is how they manipulated the camera with a set given orientation via:

local cameraRotationCFrame = CFrame.Angles(0, cameraRotation.X, 0)*CFrame.Angles(cameraRotation.Y, 0, 0)

Where camerarotation is a vector2 constantly changing variable based on mouse delta.

So here this should work, btw try using mp4 to embed easier next time.

Local script should work in starter character or starter player. Creates a first person view with parts visible like clone trooper realism but with none of the extra cool features and angle clamping.

local camera = workspace.CurrentCamera
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local player = game.Players.LocalPlayer
camera.CameraType = Enum.CameraType.Scriptable

local cameraRotation = Vector2.new(0,math.rad(0))

RunService.RenderStepped:Connect(function()
	if UserInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton2) then
		UserInputService.MouseBehavior = Enum.MouseBehavior.LockCurrentPosition
	else
		UserInputService.MouseBehavior = Enum.MouseBehavior.Default
	end
	camera.CameraType = Enum.CameraType.Scriptable
	--keep current rotation move to humanoid root part
	local headPosition = player.Character.Head.Position
	
	local mouseDelta = UserInputService:GetMouseDelta()
	cameraRotation = cameraRotation - mouseDelta/200

	local cameraRotationCFrame = CFrame.Angles(0, cameraRotation.X, 0)*CFrame.Angles(cameraRotation.Y, 0, 0)
	camera.CFrame = cameraRotationCFrame+headPosition -- rotate
end)
2 Likes

Your clone trooper thing seems to be using player character’s and I dont have characters in my game. I want to make freecam for players with no characters - the one we have in roblox studio edit mode (not testing mode).

I already looked at official documentation previously and used this code but it didnt help:

local cameraRotationX, cameraRotationY, cameraRotationZ = camera.CFrame:ToEulerAnglesXYZ()
camera.CFrame *= CFrame.Angles(0, cameraRotationX, 0) * CFrame.Angles(cameraRotationY, 0, 0)

This is the result of the code above:
new.wmv (1.3 MB)
The camera is just rotating around on its own like crazy.

Thanks for the effort I appreciate it…

Then modify my version so that instead of going to the head position as seen here:

Move it to your free cam position.
(press w and the position changes by going forward by the camera look vector to make it go where it’s looking)

As for why your attempt doesn’t work, it doesn’t make sense.

local cameraRotationCFrame = CFrame.Angles(0, cameraRotation.X, 0)*CFrame.Angles(cameraRotation.Y, 0, 0)

This defines the cameras current rotation like how a part is defined with orientation of (0,0,-90) for example.

Then you just continually CFrame multiply this orientation by itself? The orientation get added up according to CFrame multiplication (0,0,-90) + (0,0,-90) of course it’s going to spin like crazy.

2 Likes

Your code seems to be nothing at all. Right mouse button does nothing.
My character can walk around but camera is inside my head but i cant move the camera with right mouse button.

Edit: whoops, looks like I accidentally deleted the right mouse button uis part, so now it works, I will try to apply this to freecam script and see if it works and if it does I will let you know by marking your post as solution. The code was very helpful :smiley:

Right click and drag to rotate the camera like in third person mode. Right-click locks the mouse button and allows the mouse delta to be read and hence rotate the camera.

I did it so I could stop simulation more easily instead of locking the mouse in first person forever.

Thank you for your solution! I’ve tried a lot of methods and none of them worked! Your solution is exactly what I needed. Turns out that I need to add camera’s current position to the rotation CFrame and set it to be the camera’s CFrame:

-- before render stepped:
local cameraRotation = Vector2.new(0, math.rad(0))

-- inside render stepped:
local pos = camera.CFrame.Position

local mouseDelta = uis:GetMouseDelta()
local SLOWNESS = 100

cameraRotation = cameraRotation - mouseDelta / SLOWNESS

local cameraRotationCFrame = CFrame.Angles(0, cameraRotation.X, 0) * CFrame.Angles(cameraRotation.Y, 0, 0)
camera.CFrame = cameraRotationCFrame + pos -- rotate