How would I offset the camera with rotation?

I’m trying to make a recoil system like CSGO (where the camera goes back down after a bit)
and I don’t know how to do it.

1 Like

I would suggest using springs for this, BlackShibe’s fps framework 2020 uses his spring module

Look through that when he makes gun sway, the usage for the spring module is explained in the article above.

I would suggest making a RenderStepped bind and do

local Recoil = CamSpring:update(dt)--<<deltatime is the only thing passed into RenderStepped 
game.Workspace.CurrentCamera.CFrame *= CFrame.Angles(Recoil.X, Recoil.Y, Recoil.Z)
1 Like

Couldnt you just play an animation instead of offset the camera?

1 Like

No, I want the camera to move without animations since animations are only set in one way it won’t be the same as making it procedurally.

1 Like

Here is a function I made for you that works for models, baseparts or any PVInstance (Have a location in the world) and also respects the new pivot feature!

local function offsetObjectRotation(object : PVInstance | Camera, rotationOffsetXYZ : Vector3)
	if object:IsA("PVInstance") then
		local oldCFrame = object:GetPivot()
		local newCFrame =  oldCFrame * CFrame.Angles(rotationOffsetXYZ.X, rotationOffsetXYZ.Y, rotationOffsetXYZ.Z)

	elseif object:IsA("Camera") then
		local oldCFrame = object.CFrame
		local newCFrame =  oldCFrame * CFrame.Angles(rotationOffsetXYZ.X, rotationOffsetXYZ.Y, rotationOffsetXYZ.Z)

		object.CFrame = newCFrame
		error("Cannot rotate the object of class name "..object.ClassName)

Here is an example on how to use it
The following code offset the rotation of it’s parent part by 45 degrees along the local X axis of the object.

offsetObjectRotation(script.Parent,, 0, 0))

Before running the example code

After running the example code


1 Like

That’s cool but, how would it work on the camera?

The camera doesn’t have a pivot unless I stand corrected

local camera = workspace.CurrentCamera
camera .CameraType = Enum.CameraType.Scriptable

function Recoil()
    camera.CFrame = camera.CFrame:ToWorldSpace(CFrame.Angles(math.rad(0.05), math.rad(0.1), 0) 

You will prob need to change values since i put random numbers, put thats how I would do some recoil

1 Like

If you want it to be smooth recoil instead of jittery recoil springs would be the way to go.

Edit: they require a bit more implementation but i think its worth it

offsetObjectRotation(camera,, angleY, angleZ))

If you need more information, let me know!

1 Like

Ohhhh okay thanks I’ll try that out

1 Like

As I thought, the camera doesn’t have a pivot

15:10:45.118 GetPivot is not a valid member of Camera “Workspace.Camera” - Client - Framework:314
15:10:45.118 Stack Begin - Studio
15:10:45.118 Script ‘Workspace.TruestBlu.Framework’, Line 314 - function offsetObjectRotation - Studio - Framework:314
15:10:45.118 Script ‘Workspace.TruestBlu.Framework’, Line 353 - Studio - Framework:353
15:10:45.119 Stack End - Studio


I think thats because camera isnt a BasePart

Alright, let me fix that, didn’t know that the camera doesn’t have a PVInstance

1 Like

I’ve replaced them with cframe so hopefully it’ll work

I edited my post, try it out @mehhhify

Okay so I want the camera to move correspondingly to a number, lets say hmmm it’s 4. When that number goes down I also want the camera to move down with it and vice versa.

1 Like

You shouldn’t use a direct offset then, maybe you should store an offset and apply it to the camera. as a cframe is basically a mathematical matrix.

and then you can always edit that stored offset.
for that, I’ll try to come up with something for you real quick

Alright so here is a quick prototype that works

local oldOffset = -- Don't edit this!
local offset =

-- (Optional): Will accumulate the time in seconds since the script started
local t = 0

	-- (Optional): Accumulate the time in seconds
	t += delta
	-- Cancel out the offset we applied in the previous frame
	cam.CFrame *= oldOffset:Inverse()
	-- Apply the new offset
	cam.CFrame *= offset
	-- Store the offset we have applied so we cancel it in the next frame
	oldOffset = offset
	-- Update the offset that will applied!
	offset = CFrame.Angles(math.sin(t), 0, 0)  --You can change this however you want!
	-- Proof (Optional): You can update the original cframe without affecting the offset
	cam.CFrame *=*10, 0, 0) --You can change this however you want!

This gives you a relative cframe that you can play with without overriding the original camera cframe.
If you’re interested, I can make it as a robust function for you!


Thank you so much and no, it’s alright.

1 Like

EDIT: Added comments to help you understand the code!

1 Like