Hey developers,
TweenService is probably the best choice for tweening between 2 points. However, when you have more than 2 points, you have to do something like this:
This doesn’t look good and is pretty outdated. But there’s a solution: Bézier curves.
CutsceneService is a module which specializes in cutscenes. It is easy to use, fully customizable and has a wide range of features.
Guides
Getting started
Note: It is highly recommended to use the plugin as it greatly facilitates the work.
Firstly, get the module here and insert into your game via the Toolbox (preferably ReplicatedStorage).
After that we’ll set up a cutscene. Create a folder in Workspace and name it Cutscene1
.
Then insert parts (also called points) into it. Name the parts 1
, 2
, 3
, etc. The cutscene starts at 1 and ends at the last point.
Position the parts and make sure they are looking in the right direction.
The more points in a cutscene, the more calculations have to be done - don’t add unnecessarily many!
Now create a LocalScript in StarterGui and require the module:
local CutsceneService = require(game.ReplicatedStorage.CutsceneService)
Use the :Create(folder, duration)
function to create a new cutscene.
local CutsceneService = require(game.ReplicatedStorage.CutsceneService)
local cutscene1 = CutsceneService:Create(workspace.Cutscene1, 5)
The cutscene object has 5 functions:
- Play
- Pause
- Resume
- Cancel
- Destroy
After adding :Play()
, run the game and see how the cutscene looks. You might want to reposition or rotate some parts.
local CutsceneService = require(game.ReplicatedStorage.CutsceneService)
local cutscene1 = CutsceneService:Create(workspace.Cutscene1, 5)
task.wait(4)
cutscene1:Play()
Easing & Special functions
You mostly don’t want just a plain cutscene. There are easing styles, easing directions and special functions which you can add to your cutscene.
When I told you that the Create
function only has 2 parameters, I lied. You can actually add as many arguments as you want.
The order of the arguments (after the first two) doesn’t matter.
For easings, you can either use Enums or the name of a specific easing function (look in the child of the CutsceneService module).
CutsceneService:Create(workspace.Cutscene1, 5, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut)
CutsceneService:Create(workspace.Cutscene1, 5, "InOutSine")
Unlike TweenService, CutsceneService has the EasingDirection OutIn
(only callable through strings).
Special functions are called with a string. You can also use CutsceneService.Enum
to quickly autocomplete the name. In this example we will use CurrentCameraPoint
.
CutsceneService:Create(workspace.Cutscene1, 5, "CurrentCameraPoint")
CutsceneService:Create(workspace.Cutscene1, 5, CutsceneService.Enum.CurrentCameraPoint)
Here is an uncopylocked example place.
Queues
Queues let you play multiple cutscenes successively.
After creating some cutscenes, you can create a queue like this:
local queue1 = CutsceneService:CreateQueue(cutscene1, cutscene2, cutscene3)
Queues have the same 5 functions like cutscenes:
- Play
- Pause
- Resume
- Cancel
- Destroy
It also has a property called CurrentCutscene
, which represents the cutscene it currently plays.
Finally, it is possible to loop a single cutscene like this:
cutscene1:Play()
cutscene1.Next = cutscene1
You can loop a queue like this:
local queue = CutsceneService:CreateQueue(cutscene1, cutscene2, cutscene3)
queue:Play()
cutscene3.Next = cutscene1
The Next
property represents a cutscene which will be automatically played after this one. Please note that this property will be overwritten/removed when the cutscene is in a queue and a function of the queue (like Play) is called.
Happy creating!
Advanced tips & tricks
This section requires full understanding of the other guides.
An advantage of CutsceneService is that many useful things, that are normally internal, are available as API here. However I won’t document most of them, that’s why I will present some of them in this section.
PreviousCameraType and PreviousCoreGuis
These are properties that get created when a cutscene or queue is played. They contain the CameraType and CoreGui settings from before the playback, since they need to be restored after the cutscene.
Hence you can for example make it so the camera doesn’t go back to the character immediately:
cutscene1:Play()
cutscene1.PreviousCameraType = Enum.CameraType.Scriptable
for k in cutscene1.PreviousCoreGuis do
cutscene1.PreviousCoreGuis[k] = false
end
cutscene1.Completed:Connect(function()
task.wait(3) --wait 3 seconds, then change the settings back to normal
workspace.CurrentCamera.CameraType = Enum.CameraType.Custom
game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.All, true)
end)
Changing the points during playback
It is possible to change the points while the cutscene is playing. When you create a cutscene, in some cases you might not know the CFrame of a point that will be in the cutscene. You only know it the moment the cutscene is played, for example a point that is 50 studs above the character.
A possible solution is to create a new cutscene every time and play it immediately, but there’s a better way:
Cutscenes have the property Points
, which are simply the points you provided and during playback the property PointsCopy
, which is a temporary copy of Points
that was modified by special functions (for example a point was added). You can change these properties whenever you want, but it is recommended to change PointsCopy
only right after calling Play, otherwise the player might see a jump.
This cutscene can be found in the sample place:
local cutscene4 = CutsceneService:Create(
{}, 7, "InOutSine", --an empty table is passed as points
CutsceneService.Enum.CurrentCameraPoint, 1,
CutsceneService.Enum.CurrentCameraPoint,
CutsceneService.Enum.DisableControls
)
--this creates 2 points above the character and inserts them into the cutscene
buttons.Play4.MouseButton1Click:Connect(function()
local p1 = CFrame.lookAt(char.HumanoidRootPart.Position + Vector3.new(0, 100, 0), char.HumanoidRootPart.Position)
local p2 = CFrame.lookAt(char.HumanoidRootPart.Position + Vector3.new(0, 15, 0), char.HumanoidRootPart.Position)
cutscene4:Play()
table.insert(cutscene4.PointsCopy, 2, p1)
table.insert(cutscene4.PointsCopy, 3, p2)
end)
To be continued.
Documentation
CutsceneService
The main module, obtained with require().
Properties
Enum : {[string]: string}
Serves the purpose to quickly autocomplete special function names.
Settings : {[string]: any}
Contains settings for the CutsceneService module.
Settings
YieldPauseArgument : boolean
When using the waitTime
argument of the Pause
function, this yields the function.
Functions
Create(points : Instance | {CFrame}, duration : number, ...): Cutscene
Creates and returns the cutscene object. points
can be an instance with the points as it’s children or an array with CFrames. EasingStyles, EasingDirections and special functions can be added after duration
.
CreateQueue(...): Queue
Returns a queue of the cutscenes provided.
Cutscene
The cutscene object returned by Create
.
Properties
PlaybackState : Enum.PlaybackState
Describes the current stage of the cutscene. Possible values
Progress : number
Describes the current progress of the cutscene which starts at 0 and ends at 1. To get a percentage, multiply it by 100.
Functions
Play()
Starts the cutscene. If a cutscene is already playing on the client, it is not possible to start it.
Pause(waitTime : number?)
Halts the playback of the cutscene. If a waitTime
is given, it will automatically resume after it.
Resume()
Resumes the cutscene. It must first be played and then paused to be able to resume it.
Cancel()
Cancels the playback of the cutscene.
Events
Completed(playbackState : Enum.PlaybackState)
Fires when the cutscene finishes playing. This will happen either when the cutscene naturally finishes playing, or if it is stopped with Cancel
. A function connected to this event will be passed the PlaybackState to give indication about why the tween ended (Can be Completed
or Cancelled
).
Queue
The queue object returned by CreateQueue
.
Properties
PlaybackState : Enum.PlaybackState
refer to Cutscene
CurrentCutscene : Cutscene?
Represents the cutscene which is currently played. When the queue isn’t playing, it is nil
.
Functions
Play()
refer to Cutscene
Pause(waitTime : number?)
refer to Cutscene
Resume()
refer to Cutscene
Cancel()
refer to Cutscene
Events
Completed(playbackState : Enum.PlaybackState)
refer to Cutscene
Special functions
Functions that enhance your cutscene. They are called at Cutscene:Play
or right after the cutscene finished.
Arguments for special functions can be passed right after the string, like this: (..., "DefaultCameraPoint", 3, "DisableControls")
. DefaultCameraPoint would be passed the argument 3
. Everything except strings and Enums will count as an argument for a special function.
CustomCamera
Parameters: customCamera : Camera
Made for ViewportFrames, changes the camera whose CFrame is tweened.
DisableControls
Disables the character controls so you can’t move.
FreezeCharacter
Parameters: stopAnimations : boolean?
Anchors the HumanoidRootPart. The default for stopAnimations
is true
.
CurrentCameraPoint
Parameters: position : number?
Sets the current camera CFrame as a point. position
is the number where the point gets inserted: 1 would set it as the first point. The default is #points + 1
.
DefaultCameraPoint
Parameters: position : number?, useCurrentZoomDistance : boolean?
Calculates a CFrame which is behind the characters back and sets it as a point. The default for useCurrentZoomDistance
is true
, as you would have to change the CameraZoomDistance otherwise and there is only a workaround for that.
Changelog
Version 1.4.1
- Removed special function
YieldAfterCutscene
- Renamed
CutsceneService.Functions
toCutsceneService.Enum
- Removed the
resetCamera
parameter ofCutscene:Cancel
andQueue:Cancel
- Small optimizations
Please reply with feedback, suggestions, bugs, improvements, etc. I hope it comes in handy!