Camera Animations for cutscenes and gameplay!

To be honest, there are barely any games that use camera animations. Even though a good camera can make an attack feel much more powerful or give an awesome shot of a landscape during a cutscene. So I will be teaching how you can make camera animations, and use them in-game.

Note: This is my first ever tutorial on here, please roast me.

To start off, you’re going to need Moon Animator.

I will start by explaining how to make simple cutscenes that always appear in the same position, I recommend reading that first, since the gameplay portion will build off of that.

Simple Cutscene

Once you’ve made a new project, add a camera to it.
image

Select the CFrame track
image

And move your camera anywhere you’d like (Tip, you can use control + h to toggle the UI)
Once you’ve found a nice position press the + key to make a new keyframe
Slide the position marker forward a bit and make the next keyframe, keep doing this until you’re finished.

(Extra tip! You can add a character with an animation to your project, and animate them at the same time! This is great for syncing the camera with character animation)

Once you have finished your animation, it’s time to export.
image

It should export a folder that contains the CFrame for every frame (Based on the animation FPS, 60 by default) Place this folder in a place the client can access
image

Now that you’ve made your animation, we need to actually script it so we can run it in-game

local RunService = game:GetService("RunService")

local Character = game.Players.LocalPlayer.Character or game.Players.LocalPlayer.CharacterAdded:Wait()
local Camera = workspace.Camera

function Cinematic()
	local CinematicsFolder = nil -- Path to your folder! 

	local CurrentCameraCFrame = workspace.CurrentCamera.CFrame
	local FrameTime = 0
	local Connection
	
	Character.Humanoid.AutoRotate = false
	Camera.CameraType = Enum.CameraType.Scriptable
	

	Connection = RunService.RenderStepped:Connect(function(DT)
		FrameTime += (DT * 60) 
		-- This will convert the seconds passed (DT) to the frame of the camera we need.
		-- Then it adds it to the total amount of time passed since the animation started
		
		local NeededFrame = CinematicsFolder.Frames:FindFirstChild(tonumber(math.ceil(FrameTime)))
		
		if NeededFrame then
			Camera.CFrame = NeededFrame.Value
		else
			Connection:Disconnect()
			Character.Humanoid.AutoRotate = true
			Camera.CameraType = Enum.CameraType.Custom
			Camera.CFrame = CurrentCameraCFrame	
		end
	end)
end

Calling this “Cinematic” function, and having your folder pathed should run your cutscene!

Gameplay Cutscenes

This is essentially the same as normal cutscenes, but we will be making use of the “Reference Part” in Moon.
This is the part the camera will offset from.
image

99% of the time, when I’m making attack cutscenes, I just set this to the character’s HumanoidRootPart

Animate your camera like normal and export it, no extra steps there.

In your script, instead of setting the camera cframe like this:

Camera.CFrame = NeededFrame.Value

We multiply it by our reference part’s CFrame
(Say the character’s HumanoidRootPart)

Camera.CFrame = Character.HumanoidRootPart.CFrame * NeededFrame.Value

That’s it! just make sure you pass the correct reference part in your code depending on the cutscene.

Here’s an example in my own game!

288 Likes

gonna need this for later, thank you for tutorial!

7 Likes

Gameplay Cutscenes

More details are needed

5 Likes

Amazing tutorial, thanks for sharing!

2 Likes

where do i place the script if im done making the camera?

11 Likes

Can you put more comments in your code? Its really hard for me to understand, especially because I dont know anything about run service.

3 Likes

What happens if i fire this on 2 clients, Will the camera play on a single player’s reference part, Or both have their own referenced humanoidrootpart?

If so, How do i make it the camera uses the dominant player’s reference part?

EDIT: Nevermind, I can just change

Camera.CFrame = Character.HumanoidRootPart.CFrame * NeededFrame.Value

to

Camera.CFrame = PlayerToPlayFrom.HumanoidRootPart.CFrame * NeededFrame.Value
5 Likes

yo where do i put the script because im lazy

Thanks for this, I thought it would be more difficult than!

1 Like

StarterPlayerScripts is where i put it

1 Like

what if the animation includes objects? (e.g. projectiles, effects)

is there a way to export it and animate it or do I have to script all projectile movements myself?

2 Likes

everything that isn’t an actual rig such as effects, subtitles, projectiles will all have to be coded in manually

1 Like

super helpful and very easy, tysm!

1 Like

I would add a client event inside of starter player scripts so you can fire it easily (needs to be a local script)

how would i add particle effect using moon animator?

2 Likes

for some reason the cutscene isn’t synced to my animation, anyone know why?

1 Like

if i wanna fireClient it???

Got a question, since im doing a “fighting game”, essentially im running 90% of the code on a server script cause i need animations n stuff global. I obviously cant just post this in as its not a local script, any way i can call the function otherwise?

1 Like

Im working on a fighting game myself too, i actually have 90% on the client :sweat_smile:

Anyways, Just set up a client sided receiver for cutscene calls, use RemoteEvents to connect them together. I previously had a folder containing all cutscenes in replicatedStorage, and would just reference one of those cutscene-folders from the server, pass that to the client, and they’d play it

the old images and videos attached stopped loading, I attached some new ones.
Furthermore, I changed a bit of the code as well as adding an extra comment for some explanation.

Glad to know it helped so many people!

2 Likes