Event Sequencer

EventSequencer is a powerful framework that enables you to build live, cross-server events and cutscenes on a structured sequence of actions and triggers. More specifically, this module helps you:

  • Build an event or cutscene on a structured framework through scheduled configurations of audio, animations, and tweens.
  • Transition between multiple scenes across multiple servers, synchronizing complex animations and visuals to a timeline.
  • Seek through an event and preview the experience for testing and development purposes.

This framework has been battle tested in Roblox events like the Twenty One Pilots and 24kGoldn concerts, as well as many highly visited experiences.

 

To see EventSequencer in action within an editable place, check out the Concert template in Roblox Studio. This template is a comprehensive starting point for developers to create events/concerts and familiarize themselves with the various features and components involved.

Module Usage

Installation

To use the EventSequencer framework in an experience:

  1. Visit the EventSequencer marketplace page, click the green Get button, and confirm the transaction.

  2. In Studio, open the Toolbox (ViewToolbox).

  3. Select your toolbox Inventory section.

  4. Locate the module and click it or drag-and-drop it into the 3D view.

  5. In the Explorer window, move the entire EventSequencer folder into ServerScriptService.

Framework Modes

Replace Mode

The default framework mode is replace mode in which you design unique scenes by placing 3D objects, terrain, lighting properties, environmental effects, and user interface objects into that scene's Environment folder. When a scene loads, those objects and properties get distributed into Workspace, Terrain, and Lighting, replacing existing objects/properties to form a cloned space.

Inline Mode

An alternate framework mode is inline mode in which you similarly design unique scenes with scripting logic for their flow/events, but the framework will not destroy existing 3D objects, terrain, lighting properties, environmental effects, and user interface objects in order to clone assets/properties from a scene's Environment folder upon loading.

To enable inline mode:

  1. Inside the EventSequencer folder that you placed in ServerScriptService, drill down to and select the Inline value inside the ReplicatedStorage folder.

  2. In the Properties window, toggle on its Value checkbox.

Creating Scenes

A scene is essentially part of an overall event or a cutscene wrapped up in a series of folders. Each scene contains scripting logic that defines its flow/events, and a scene can store its own 3D objects, terrain, lighting properties, environmental effects, and user interface objects.

To get started quickly, you can find an empty scene inside the module's main folder:

  1. Expand the EventSequencer folder and locate the BlankScene folder.

  2. Move or copy the entire BlankScene folder into ReplicatedStorage.

Time Length

Each scene should have a time length, in seconds, defining its duration — just like a movie or concert has a set duration. Time length is defined as a numeric attribute on the scene's folder named TimeLength which you can set directly in Studio or programmatically through Instance:SetAttribute().

Environment

A scene's Environment folder contains everything that users see and hear, including 3D objects, terrain, lighting properties and environmental effects, and user interface objects. When a scene loads, those objects and properties get distributed into Workspace, Terrain, and Lighting, replacing existing objects/properties to form a cloned space.

The Environment folder contains the following containers:

Container Description
Client Contains all assets to load when any user (client) joins the event, such as user interface objects or an animation rig.
PlayerSpawns Contains parts where users spawn upon joining. Any part in this folder behaves similar to a SpawnLocation.
Server Contains all assets to load when a scene is first created on a server. It's recommended that most visual assets go here.
Terrain Contains scene terrain.
Lighting Contains global lighting properties as attributes, as well as modifiers like atmospheric effects and post-processing effects.

Events

A scene's Events folder is purely a placeholder for RemoteEvents that communicate between the Client and Server modules. It's not a requirement to place anything in this folder.

Client

This script executes schema logic on the client.

Server

This script executes schema logic on the server.

Scene Schemas

A scene's schema defines what happens at what point in the scene's timeline. You should define a scene's schema in both its Client and Server modules and include lifecycle hooks to manage when configurations occur.

Lifecycle Hooks

Schema lifecycle hooks let you manage when scene operations occur. A scene in production will typically run in the most simple flow:

OnSetup
 →
OnRun
 →
OnEndScene

OnRun may be interrupted when seeking:

OnSetup
 →
OnRun
 
seek
 →
OnRun
 
seek
 →
OnRun
 →
OnEndScene

All three hooks can also repeat if the scene is replayed:

OnSetup
 →
OnRun
 →
OnEndScene
 
replay
 →
OnSetup
 →
OnRun
 →
OnEndScene

Configurations

Schema configurations define the core operations of a scene, for example playing audio at 00:32, queuing an animation to sync with that audio, scheduling a scene event like a fireworks show, and more. Every configuration supports certain callback functions where the first parameter (self) is the configuration instance.

Seeking Scenes

A unique feature of EventSequencer is the ability to "seek" around scenes as you might seek through a video. In Replace Mode, you can also switch between scenes to preview an entire multi-scene event before deploying it to production.

Scene seeking is not accessible to everybody since users simply enjoying the event should not have the ability to control its time flow. Instead, you must grant seeking permission based on the event's PlaceId as well as specific UserIds and/or groups and roles within them.

  1. Create a new Script within ServerScriptService.

  2. Paste the following code into the new script.

    Script - Set Seeking Permissions

    1local ReplicatedStorage = game:GetService("ReplicatedStorage")
    2
    3local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
    4
    5EventSequencer.setSeekingPermissions({
    6 placeIDs = {},
    7 userIDs = {},
    8 groups = {
    9 {GroupID = , MinimumRankID = },
    10 }
    11})
    12
  3. Fill in the following tables within the setSeekingPermissions call as follows:

placeIDs Comma-delimited list of PlaceId values to support seeking within.
userIDs Comma-delimited list of UserId values of users who can seek within the supported places.
groups Comma-delimited list of tables, each containing a group ID and the minimum rank of that group's members who can seek within the supported places.

Scene Manager Plugin

The Scene Manager plugin is a useful tool for loading and unloading scenes, lighting, and terrain. Unless you're using Inline Mode, it's highly recommended that you use this plugin instead of manually placing/editing scene objects and properties.

To install the plugin:

  1. From Studio's View menu, open the Toolbox.

  2. With the Marketplace tab selected, select Plugins from the dropdown menu.

  3. In the search field, type Scene Manager and press Enter to locate the plugin.

  4. Click the plugin's icon to view its details and then click the blue Install button.

  5. Once the plugin is installed, it appears in Studio's Plugins tab.

Loading and Unloading Scenes

As outlined in Creating Scenes, a scene's Environment folder contains everything that users see and hear, including 3D objects. The plugin helps you quickly load a scene's assets into or out of organized folders within the workspace.

Plugin Action Description
Load Client If the scene's client content is unloaded, moves its Environment/Client folder into the Workspace/ScenesClient folder.
Load Server If the scene's server content is unloaded, moves its Environment/Server folder into the Workspace/ScenesServer folder.
Unload Client If the scene's client content is loaded, moves its Client folder from Workspace/ScenesClient back to the [Scene]/Environment folder.
Unload Server If the scene's server content is loaded, moves its Server folder from Workspace/ScenesServer back to the [Scene]/Environment folder.
Unload All Scenes Moves every loaded scene's Client and Server folder back to its Environment folder.

Saving and Loading Lighting

The top-level Lighting service stores all of a place's lighting properties and visual effects. Since it's a top-level service, you cannot manually move it to a particular scene's Environment/Server or Environment/Client folder. Instead, you can utilize the plugin to copy its properties and children to the scene's Environment/Lighting folder.

  1. Configure the scene's lighting properties, post-processing effects, atmospheric effects, and skyboxes through the top-level Lighting service.

  2. In the Scene Manager plugin window, click Save Lighting for the desired scene.

  3. Select and expand that scene's Environment/Lighting folder and you'll see the same lighting properties as attributes of the folder, as well as cloned children of the top-level Lighting service.

    Cloned instances
    Cloned instances
    Saved attributes
    Saved attributes

    Once lighting properties and children are saved for a scene, you can quickly load them back into the top-level Lighting service by clicking Load Lighting from the plugin window.

Saving and Loading Terrain

Since Terrain is a top-level class within Workspace, you cannot manually move generated or sculpted terrain to a particular scene's Environment/Server or Environment/Client folder. Instead, you can utilize the plugin to copy it to the scene's Environment/Terrain folder.

  1. Configure the scene's terrain through the top-level Terrain service.

  2. In the Scene Manager plugin window, click Save Terrain for the desired scene.

  3. Select and expand that scene's Environment/Terrain folder and you'll see a TerrainRegion object which represents the saved terrain.

    Once terrain is saved for a scene, you can quickly load it back into the top-level Terrain service by clicking Load Terrain from the plugin window.

API Reference

Schema Lifecycle Hooks

OnSetup

The OnSetup lifecycle hook is intended for initializing assets and variables that will be referenced in OnRun or OnEndScene, setting up connections that are intended to last for the duration of the scene, etc. This hook receives the timePositionObject parameter which lets you read the current time at setup.

Client Schema

1local ReplicatedStorage = game:GetService("ReplicatedStorage")
2
3local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
4
5local Schema = EventSequencer.createSchema()
6
7local clientEnvironment
8local serverEnvironment
9local dummy
10
11Schema.OnSetup = function(timePositionObject)
12 print("OnSetup (Client)")
13
14 -- Access scene environments; does not apply to Inline Mode
15 clientEnvironment = EventSequencer.getCurrentSceneEnvironment()
16 serverEnvironment = EventSequencer.getCurrentServerEnvironmentFromClient()
17 -- Wait for assets
18 dummy = clientEnvironment:WaitForChild("Dummy")
19
20 print("Current time is:", timePositionObject.Value)
21end
22
Server Schema

1local ReplicatedStorage = game:GetService("ReplicatedStorage")
2
3local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
4
5local Schema = EventSequencer.createSchema()
6
7local serverEnvironment
8local partColorConnection
9local changePartColorEvent = script.Parent.Events.ChangePartColor
10
11Schema.OnSetup = function(timePositionObject)
12 print("OnSetup (Server)")
13
14 -- Access scene environment; does not apply to Inline Mode
15 serverEnvironment = EventSequencer.getCurrentSceneEnvironment()
16 partColorConnection = changePartColorEvent.OnServerEvent:Connect(function(player, changedPart, newColor)
17 serverEnvironment.changedPart.Color = newColor
18 end)
19
20 print("Current time is:", timePositionObject.Value)
21end
22

OnRun

OnRun is the main operational lifecycle hook within a schema. It should contain all timed configurations for the scene, from playing audio or an animation to scheduling an event like a fireworks display.

Client Schema

1Schema.OnRun = function()
2 print("OnRun (Client)")
3
4 local MainAudio = Schema:audio({
5 StartTime = 1,
6 SoundId = "rbxassetid://1838673350",
7 OnStart = function(self)
8 print("Audio playing")
9 end,
10 OnEnd = function(self)
11 print("Audio ended")
12 end
13 })
14end
15

OnEndScene

The OnEndScene lifecycle hook is useful for cleaning up anything outstanding in the scene, such as disconnecting connections created in OnSetup or OnRun that remain for the duration of the scene.

Server Schema

1Schema.OnEndScene = function()
2 print("OnEndScene (Server)")
3
4 if partColorConnection then
5 partColorConnection:Disconnect()
6 partColorConnection = nil
7 end
8end
9

Schema Configurations

audio

Creates a Sound object in the workspace which plays at a certain time. The sound is then deleted after the scene is over or after the Sound object finishes playing.

Configuration Key Description
StartTime When to play the audio in relation to the scene duration, in seconds.
SoundId Asset ID of the audio to play.
OnStart Custom function to fire when the audio begins playing.
OnEnd Custom function to fire when the audio finishes playing.
Volume Volume of the Sound object; default is 0.5.
Client Schema

1Schema.OnRun = function()
2 print("OnRun (Client)")
3
4 local MainAudio = Schema:audio({
5 StartTime = 1,
6 SoundId = "rbxassetid://1838673350",
7 OnStart = function(self)
8 print("Audio playing")
9 end,
10 OnEnd = function(self)
11 print("Audio ended")
12 end
13 })
14end
15

animate

Creates an Animation which plays at a certain time.

Configuration Key Description
StartTime When to play the animation in relation to the scene duration, in seconds.
EndTime Optional time when to end the animation in relation to the scene duration, in seconds.
Rig The animation rig to play the animation on.
AnimationId Asset ID of the animation to play.
Speed Playback speed of the animation; default is 1.
FadeInTime Amount of time to fade in the animation, in seconds; default is 0.2 (seconds).
FadeOutTime Amount of time to fade out the animation, in seconds; default is 0.2 (seconds).
OnStart Custom function to fire when the animation begins playing.
OnEnd Custom function to fire when the animation finishes playing.
Looped Whether to loop the animation; default is false.
SyncToAudio Table defining whether to sync the animation to an audio configuration. Accepts the following keys:
  • Audio – Reference to an audio configuration.
  • StartAtAudioTime – When to play the animation in relation to the audio's duration.
  • EndAtAudioTime – Optional time at which to end the animation in relation to the audio's duration.
Client Schema

1Schema.OnRun = function()
2 print("OnRun (Client)")
3
4 local MainAudio = Schema:audio({
5 StartTime = 1,
6 SoundId = "rbxassetid://1838673350",
7 })
8
9 local DanceAnimation = Schema:animate({
10 AnimationId = "rbxassetid://3695333486",
11 Rig = Dummy,
12 Speed = 1,
13 FadeInTime = 0.1,
14 FadeOutTime = 0.3,
15 SyncToAudio = {
16 Audio = MainAudio,
17 StartAtAudioTime = 5,
18 },
19 OnStart = function(self)
20 print("Animation playing")
21 end,
22 OnEnd = function(self)
23 print("Animation stopped")
24 end
25 })
26end
27

tween

Creates a configurable Tween which is preserved in seeking and in dynamic join, meaning you can chain tweens at separate points in time and everything should play and sync as expected.

Configuration Key Description
StartTimes Table of start times in relation to the scene duration, in seconds.
Tween Table defining the object and properties to tween. Accepts the following keys:
  • Object – The object to tween.
  • InfoTweenInfo instance for the tween, defining its duration, EasingStyle, EasingDirection, etc.
  • Properties – Object properties and associated target values for the tween.
OnStart Custom function to fire when the tween begins playing.
OnHeartbeat Custom function to fire on every Heartbeat; receives the tween alpha as its second parameter.
OnEnd Custom function to fire when the tween finishes playing.
SyncToAudio Table defining whether to sync the tween to an audio configuration. Accepts the following keys:
  • Audio – Reference to an audio configuration.
  • StartAtAudioTimes – Table of start times defining when to play the tween in relation to the audio's duration.
Client Schema

1Schema.OnRun = function()
2 print("OnRun (Client)")
3
4 local MainAudio = Schema:audio({
5 StartTime = 1,
6 SoundId = "rbxassetid://1838673350",
7 })
8
9 local LightFadeOut = Schema:tween({
10 StartTimes = {29.884},
11 Tween = {
12 Object = game:GetService("Lighting"),
13 Info = TweenInfo.new(2, Enum.EasingStyle.Sine, Enum.EasingDirection.Out),
14 Properties = {
15 Brightness = 0,
16 }
17 },
18 SyncToAudio = {
19 Audio = MainAudio,
20 StartAtAudioTimes = {5, 7.2, 9.4, 11.6},
21 },
22 OnStart = function(self)
23 print("Tween playing")
24 end,
25 OnHeartbeat = function(self, alpha)
26 print("Tween alpha", alpha)
27 end,
28 OnEnd = function(self)
29 print("Tween completed")
30 end,
31 })
32end
33

interval

Executes a custom callback function over a specified duration on a specified frequency, in seconds. Useful for repeating events like flashing lights, pulsing an audio's intensity, etc. The lowest possible frequency is 0 seconds, but technically the minimum frequency is always clamped to Heartbeat.

Configuration Key Description
StartTime Beginning of the interval duration in relation to the scene duration, in seconds.
EndTime End of the interval duration in relation to the scene duration, in seconds.
Frequency How often the OnInterval function should fire, in seconds, with the first execution being at StartTime.
OnStart Custom function to fire when the series of intervals begins.
OnInterval Custom function to fire at every interval within the specified duration (StartTime to EndTime).
OnEnd Custom function to fire when the series of intervals ends.
SyncToAudio Table defining whether to sync the interval duration to an audio configuration. Accepts the following keys:
  • Audio – Reference to an audio configuration.
  • StartAtAudioTime – When to start the interval duration in relation to the audio's duration.
  • EndAtAudioTime – Optional time at which to end the interval duration in relation to the audio's duration.
Client Schema

1Schema.OnRun = function()
2 print("OnRun (Client)")
3
4 local MainAudio = Schema:audio({
5 StartTime = 1,
6 SoundId = "rbxassetid://1838673350",
7 })
8
9 local ClientTimerUpdate = Schema:interval({
10 Frequency = 1,
11 SyncToAudio = {
12 StartAtAudioTime = 2.5,
13 EndAtAudioTime = 10,
14 Audio = MainAudio
15 },
16 OnInterval = function(self)
17 print(MainAudio.Sound.TimePosition, MainAudio.CurrentSoundIntensityRatio)
18 end,
19 })
20end
21

schedule

Similar to interval except that you can define multiple specific starting times for the same event, such as scheduling a fireworks display twice in a scene.

Configuration Key Description
StartTimes Table of start times in relation to the scene duration, in seconds.
OnStart Custom function to fire at every specified time in the StartTimes table.
Skippable Boolean defining whether the scheduled event can be skipped for users who join late, or for when seeking ahead of a scheduled start time. If set to false, all event start times scheduled before the join/seek time will occur at that join/seek time. If set to true, only the start times scheduled after join/seek will occur. Default is false.
SyncToAudio Table defining whether to sync the schedule to an audio configuration. Accepts the following keys:
  • Audio – Reference to an audio configuration.
  • StartAtAudioTimes – Table of start times defining when to fire the OnStart function in relation to the audio's duration.
Client Schema

1Schema.OnRun = function()
2 print("OnRun (Client)")
3
4 Schema:schedule({
5 StartTimes = {5, 27.25},
6 OnStart = function(self)
7 -- Initialize temporary heartbeat connection
8 local tempConnection = RunService.Heartbeat:Connect(function()
9
10 end)
11 -- Inform framework of connection
12 Schema:inform(tempConnection)
13 end
14 })
15end
16

inform

Informs the framework of any modules, UI objects, connections, etc. which are created in the OnRun lifecycle hook, ensuring they are properly cleaned up when seeking. Use cases include:

  • Informing the framework of a temporary ad-hoc connection such as RunService.Heartbeat so that the connection is cleaned up when seeking to an earlier point in the scene's duration.

    Server Schema

    1Schema.OnRun = function()
    2 print("OnRun (Server)")
    3
    4 Schema:schedule({
    5 StartTimes = {5},
    6 OnStart = function(self)
    7 -- Initialize temporary heartbeat connection
    8 local tempConnection = RunService.Heartbeat:Connect(function()
    9
    10 end)
    11 -- Inform framework of connection
    12 Schema:inform(tempConnection)
    13 end
    14 })
    15end
    16
  • Calling a custom "cleanup" function in a ModuleScript that initializes a connection or other reference during the OnRun lifecycle hook.

    Server Schema

    1local ReplicatedStorage = game:GetService("ReplicatedStorage")
    2local RunService = game:GetService("RunService")
    3
    4local customModule = require(ReplicatedStorage:WaitForChild("CustomModule"))
    5
    6local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
    7
    8local Schema = EventSequencer.createSchema()
    9
    10Schema.OnRun = function()
    11 print("OnRun (Server)")
    12
    13 Schema:schedule({
    14 StartTimes = {5},
    15 OnStart = function(self)
    16 -- Call "init" function in custom module
    17 customModule.init()
    18 -- Call "clean" function in custom module on scene cleanup
    19 Schema:inform(customModule, customModule.clean)
    20 end,
    21 })
    22end
    23
    ModuleScript - CustomModule

    1local RunService = game:GetService("RunService")
    2
    3local CustomModule = {}
    4
    5CustomModule.init = function()
    6 -- Initialize heartbeat connection
    7 CustomModule.connection = RunService.Heartbeat:Connect(function()
    8
    9 end)
    10end
    11
    12CustomModule.clean = function()
    13 -- Disconnect and clear heartbeat connection
    14 if CustomModule.connection then
    15 CustomModule.connection:Disconnect()
    16 CustomModule.connection = nil
    17 end
    18end
    19
    20return CustomModule
    21

Functions

loadScene

loadScene(sceneName:string, startTime:number?)

Programmatically loads a scene by sceneName and starts it at startTime from its beginning. There will be a 5 second "grace period" for the scene to load from the server before the seek occurs and the scene starts playing. This means that if you call loadScene("[SceneName]", 20) at exactly 4:15:00 PM, the framework will wait 5 seconds in addition to the requested 20, kicking off the scene at 4:15:25 PM.

Script

1local ReplicatedStorage = game:GetService("ReplicatedStorage")
2
3local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
4
5-- Figure out next scene to load when current scene finishes
6EventSequencer.onOrchestrationFinished:Connect(function(endedSceneName)
7 if endedSceneName == "PreShow" then
8 -- "PreShow" ended; load the first scene in the concert
9 EventSequencer.loadScene("Track1")
10 elseif endedSceneName == "Track1" then
11 -- "Track1" ended; load the second scene in the concert
12 EventSequencer.loadScene("Track2")
13 else
14 -- Loop back to the pre-show scene
15 EventSequencer.loadScene("PreShow")
16 end
17end)
18

createSchema

createSchema():table

Returns an instance of the scene schema to create logic for the scene.

Client Schema

1local ReplicatedStorage = game:GetService("ReplicatedStorage")
2
3local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
4
5local Schema = EventSequencer.createSchema()
6
7Schema.OnSetup = function(timePositionObject)
8 print("OnSetup (Client)")
9end
10

seek

seek(time:number)

Seeks to the time value, in seconds, from the currently loaded scene's beginning.

Script

1local ReplicatedStorage = game:GetService("ReplicatedStorage")
2
3local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
4
5EventSequencer.seek(95.58)
6

setSceneWarningTime

setSceneWarningTime(endSceneTimeWindow:number)

Sets the amount of time from the end of all scenes at which a warning is dispatched. You can detect the warning either client-side through onSceneEndingWarningForClient or server-side through onSceneEndingWarningForServer.

Script

1local ReplicatedStorage = game:GetService("ReplicatedStorage")
2
3local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
4
5-- Load scene
6EventSequencer.loadScene("BeautifulScene")
7
8-- Set warning time to 5 seconds before the scene ends
9EventSequencer.setSceneWarningTime(5)
10
11-- Detect when scene is about to end
12EventSequencer.onSceneEndingWarningForServer:Connect(function()
13 warn("Scene is about to end!")
14end)
15

setSeekingPermissions

setSeekingPermissions(permissions:table)

Grants seeking permission based on the event's PlaceId as well as specific UserIds and/or groups and roles within them. See Seeking and Switching Scenes for more information.

getCurrentSceneEnvironment

getCurrentSceneEnvironment():Folder YIELDS

Returns the current scene's client-side or server-side Environment folder, depending on whether it's called from the Client schema script or Server schema script respectively.

Client Schema

1local ReplicatedStorage = game:GetService("ReplicatedStorage")
2
3local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
4
5local Schema = EventSequencer.createSchema()
6
7local clientEnvironment
8local serverEnvironment
9
10Schema.OnSetup = function(timePositionObject)
11 print("OnSetup (Client)")
12
13 -- Access scene environments; does not apply to Inline Mode
14 clientEnvironment = EventSequencer.getCurrentSceneEnvironment()
15 serverEnvironment = EventSequencer.getCurrentServerEnvironmentFromClient()
16
17 print("Current time is:", timePositionObject.Value)
18end
19
Server Schema

1local ReplicatedStorage = game:GetService("ReplicatedStorage")
2
3local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
4
5local Schema = EventSequencer.createSchema()
6
7local serverEnvironment
8local partColorConnection
9local changePartColorEvent = script.Parent.Events.ChangePartColor
10
11Schema.OnSetup = function(timePositionObject)
12 print("OnSetup (Server)")
13
14 serverEnvironment = EventSequencer.getCurrentSceneEnvironment()
15
16 partColorConnection = changePartColorEvent.OnServerEvent:Connect(function(player, changedPart, newColor)
17 serverEnvironment.changedPart.Color = newColor
18 end)
19end
20

getCurrentServerEnvironmentFromClient

getCurrentServerEnvironmentFromClient():Folder YIELDS

Returns the current scene's server-side Environment folder. Unlike getCurrentSceneEnvironment, you can call this from the Client schema script.

Client Schema

1local ReplicatedStorage = game:GetService("ReplicatedStorage")
2
3local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
4
5local Schema = EventSequencer.createSchema()
6
7local clientEnvironment
8local serverEnvironment
9
10Schema.OnSetup = function(timePositionObject)
11 print("OnSetup (Client)")
12
13 -- Access scene environments; does not apply to Inline Mode
14 clientEnvironment = EventSequencer.getCurrentSceneEnvironment()
15 serverEnvironment = EventSequencer.getCurrentServerEnvironmentFromClient()
16
17 print("Current time is:", timePositionObject.Value)
18end
19

isLoadingScene

isLoadingScene():boolean

Called from the server to know if a scene is currently loading.

Script

1local ReplicatedStorage = game:GetService("ReplicatedStorage")
2
3local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
4
5print(EventSequencer.isLoadingScene())
6
7while EventSequencer.isLoadingScene() do
8 task.wait()
9end
10print("Scene loaded")
11

Events

onSceneEndingWarningForClient

onSceneEndingWarningForClient(): RBXScriptSignal

Fires on the client before the scene is about to end. The default time is 3 seconds, but you can configure it through setSceneWarningTime. This event can only be connected in a LocalScript.

LocalScript

1local ReplicatedStorage = game:GetService("ReplicatedStorage")
2
3local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
4
5-- Detect when scene is about to end (client-side)
6EventSequencer.onSceneEndingWarningForClient:Connect(function()
7 warn("Scene is about to end!")
8end)
9

onSceneEndingWarningForServer

onSceneEndingWarningForServer(): RBXScriptSignal

Fires on the server before the scene is about to end. The default time is 3 seconds, but you can configure it through setSceneWarningTime. This event can only be connected in a Script.

Script

1local ReplicatedStorage = game:GetService("ReplicatedStorage")
2
3local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
4
5-- Detect when scene is about to end (server-side)
6EventSequencer.onSceneEndingWarningForServer:Connect(function()
7 warn("Scene is about to end!")
8end)
9

onSceneLoadedForClient

onSceneLoadedForClient(): RBXScriptSignal

Fires on the client when the scene is starting. This event can only be connected in a LocalScript.

LocalScript

1local ReplicatedStorage = game:GetService("ReplicatedStorage")
2
3local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
4
5-- Detect when scene is starting (client-side)
6EventSequencer.onSceneLoadedForClient:Connect(function()
7 warn("Scene is starting!")
8end)
9

onOrchestrationFinished

onOrchestrationFinished(): RBXScriptSignal

Fires on the server when a scene has reached its time length and has effectively ended. This event receives an endedSceneName string name argument for the scene that just finished and you can chain off this event to conditionally load another scene. Can only be connected in a Script.

Script

1local ReplicatedStorage = game:GetService("ReplicatedStorage")
2
3local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
4
5-- Figure out next scene to load when current scene finishes
6EventSequencer.onOrchestrationFinished:Connect(function(endedSceneName)
7 if endedSceneName == "PreShow" then
8 -- "PreShow" ended; load the first scene in the concert
9 EventSequencer.loadScene("Track1")
10 elseif endedSceneName == "Track1" then
11 -- "Track1" ended; load the second scene in the concert
12 EventSequencer.loadScene("Track2")
13 else
14 -- Loop back to the pre-show scene
15 EventSequencer.loadScene("PreShow")
16 end
17end)
18