Animating the camera?

Hello, everyone

This is something i am really in need of help recently, And as it’s something complicated to explain and most likely really complicated to do, I have not reached the results i’m looking for yet

I feel that this topic needs more attention from the community since this is something that makes FPS games look much better,

What i want to achieve

I will try to make this as easy as i can
So, most recent FPS games have what i like to call “Camera Animations”
Here’s an example of what i am talking about:

https://gyazo.com/e7564154a1508240d29cc96a04875b67

(Animation by hyper)

You can see that not just the arms move, but the camera moves as well.
“So you want to make an animated cutscene?” You may ask

  • Almost, but not really a cutscene.

It’s like a cutscene, but the camera does not freeze at one position while the cutscene is playing, It’s like a cutscene that, while it plays, you can freely move your camera around.

I tried to find the solution myself, and i feel i am really next to it.

Solution

I have not reached what i want yet, and this is why i am making this topic, But however, i am almost getting to the point i am trying to achieve.

Most fps games have what they call a “View Model” or a “Framework”, wich is basically a “Fake arms” model that stick to your camera,Wich makes the player think that those are his character’s arms, when in reality, it’s a fake arm model in front of your camera.

An example of what i am talking about is this:
image

What i did, and most FPS games do, is put a “Fake Camera” into the viewmodel Rig, This is what makes the “Camera Animation”. What the real Camera do, is just sync its movement to the “Fake Camera”'s Movement.

image
This red part is the “Fake Camera” of my ViewModel Rig.
It basically just plays a camera animation, And the Real Camera just follows it.

My real question with this Topic is;
How can i make the camera movement sync with the “Fake Camera”'s Movement, but without freezing the camera to the “Fake Camera”'s CFrame, got it?

For example, if the Fake Camera rotates to the right, the camera will also rotate to the right, if the Fake Camera rotates to the Left, the camera will also rotate to the left

Hope that this topic gets solved in the future,
Thank you for your attention and help.

12 Likes

Okay, hopefully I’ve understood what you wanted to correctly but I think I have a solution for this.

First I created a camera animation for a ‘fake camera part’ (like you described) to simulate recoil or whatever camera effect.

Next I just created a script that cframes the camera to the changed orientation of the fake camera part on render step. The core part of the code that you need to do this is shown below.


local prevRot = CFrame.new()
function updateCamera()
	local prevRotX, prevRotY, prevRotZ = prevRot:ToEulerAnglesYXZ()
	local currRotX, currRotY, currRotZ = cameraPart.CFrame:ToEulerAnglesYXZ()
	camera.CFrame = camera.CFrame * CFrame.Angles(prevRotX-currRotX,currRotY-prevRotY,0)
	prevRot = cameraPart.CFrame
end

runService:BindToRenderStep("updateLoop",1, updateCamera)

Essentially the updateCamera function just finds out how much the camera part’s orientation has changed since the last render step and changes the camera’s cframe by that amount.

The finished result looks like the below.

You can probably do a better job than me at creating a convincing recoil animation, but essentially the player can freely move their camera still whilst the animation plays, just from the changed camera’s cframe. Is this what you meant or have I misunderstood? If you have any further questions about the code then feel free to ask.

EDIT: I’ve just made an observation that it should be prevRotX-currRotX when setting the CFrame instead of currRotX-prevRotX. I have changed this in the code above.

11 Likes

shouldnt you just save the old cframe put it to object space and * by that?

1 Like

Can you provide a coded example on how to do this, I thought of maybe doing it someway like that but couldn’t figure out how??

1 Like

That is 99% of what i meant, i will show you the only problem:

the “Fake Camera” or cameraPart, is Jointed to a “Base”, that is being placed at the camera’s CFrame every renderstep, and that is the problem.
image
like this:

game[“Run Service”].RenderStepped:connect(function()
script.Parent.Base.CFrame = workspace.CurrentCamera.CFrame
end)

As the base is being placed at the camera’s cframe, the camera just begins to spin

(sorry i dont know how to make the code colored)

1 Like

Not really, i will edit the topic and link a place with an example

local newCamCF = ViewModel.Camera.CFrame:ToObjectSpace(ViewModel.HumanoidRootPart.CFrame)
	workspace.CurrentCamera.CFrame = workspace.CurrentCamera.CFrame * newCamCF:ToObjectSpace(oldCamCF)
	
oldCamCF = newCamCF

Untested, but should work

3 Likes

This place has an example scripted framework wich you can use to understand:

1 Like

I tested and its almost what i want, i linked a place on the topic where you can understand more of what i am talking about

Im confused, a viewmodel is all that is posted in the testing place? Could you elaborate?

1 Like

the “framework”, is the viewmodel

How is a viewmodel even related to animating the camera? Do you want us to show you how to animate the viewmodel or the camera?

1 Like

its a little confusing to understand,
to explain better, go to this place:ICanIsmar Framework - Roblox

press 1 to get a weapon, fire it a couple times, reload, and look at the camera animations

try to think how that is made, you will probabbly get what i mean

Yeah, that is what I did in my post. I made it so that by animating the part you animate your camera…

1 Like

Yeah, but for some reason your code is printing “Bad argument #2 (CFrame expected got nil)” in the
line “workspace.CurrentCamera.CFrame = workspace.CurrentCamera.CFrame * newCamCF:ToObjectSpace(oldCamCF)”

1 Like

Most likely because oldcamcf was never defined at the beggining(set it to the cams cf at the start) and that was stopping it every time before it could set oldcamcf
try that

1 Like

Sorry for bringing this back up, but seems that it has a problem, the camera seems not to be tilting. I had a part rigged to torso for animating the head movement and use your code to make the camera follow the head’s orientation, here’s a test animation:
https://gyazo.com/83f1980d6717b64360dd4edcfe6761de

However when I run it in game, indeed the animation played, but the camera is “glitchy” and looks like it is attempting to rotate.
https://gyazo.com/dd78e8e6e500497d622833d4d7558b9c

Code:

local oldCamCF

function UpdateCamera()	
	if char.Torso.HeadCamera.Transform ~= CFnew(  0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1) then
		local newCamCF = char.CamPart.CFrame:ToObjectSpace(char.Torso.CFrame)
		if not oldCamCF then
			cam.CFrame = cam.CFrame * newCamCF:ToObjectSpace(newCamCF)
		else
			cam.CFrame = cam.CFrame * newCamCF:ToObjectSpace(oldCamCF)	
		end
		
		oldCamCF = newCamCF
	end
end

runservice:BindToRenderStep("ReloadAnimation",1, function()
	UpdateCamera()
end)

Any solutions to it? Thanks.

3 Likes

I also had this problem, seems like the camera does no tilt on the z axis

I think it’s possible to tilt on Z axis, or at least I hope it can, because I found a open source spring module which apply spring physics to the camera and it can set camera’s Z CFrame with the default Camera.

It uses the same approach to apply the CFrame:
I believe that p() is a function that returns an angle value:

local function updatecam()
	local x,y,z
	if cam.recoil.x and cam.recoil.x.p() then
		x = cam.recoil.x.p()
	else
		cam.recoil.x = nil
	end
	if cam.recoil.y and cam.recoil.y.p() then
		y = cam.recoil.y.p()
	else
		cam.recoil.y = nil
	end
	if cam.recoil.z and cam.recoil.z.p() then
		z = cam.recoil.z.p()
	else
		cam.recoil.z = nil
	end
	if x or y or z then
		cam.current.CoordinateFrame = cam.current.CoordinateFrame * CFrame.Angles(x or 0, y or 0, z or 0)
	end
	x,y,z = nil,nil,nil
end

game:GetService("RunService"):BindToRenderStep("RecoilCam",2000,function()
    updatecam()
end)

https://gyazo.com/769daadb9e79ba915db9700f34ecab9a

Let me know if you want the full module to have a look, I hope this works for animating the camera as well…

Edit: There’s one more thing to notice about: This camera spring module overlay the Free Camera (Shift P)'s CFrame too, however the code provided up there will not, I guess this difference explains why Z can’t be tilted? But I still don’t know why they’re different.
https://gyazo.com/941e5b79d162c5344dcf21bf13c5664f

I somehow managed to fix it, you have to use ToOrientation() to find out the Z, this might not be the best solution but at least it works for me at the moment.

-- RenderStep

		local newCamCF = char.CamPart.CFrame:ToObjectSpace(char.Torso.CFrame)
		if oldCamCF then
			--cam.CFrame = cam.CFrame * newCamCF:ToObjectSpace(newCamCF)
			local _,_,z = newCamCF:ToOrientation()
			local x,y,_ = newCamCF:ToObjectSpace(oldCamCF):ToEulerAnglesXYZ()
			cam.CFrame = cam.CFrame * CFAngles(x,y, -z)
		end
		
		oldCamCF = newCamCF
22 Likes