事件序列器是一个强大的框架,使您能够在一系列有结构的动作和触发器上构建实时跨服务器事件和过场动画。更具体地说,该模块可以帮助您:
- 通过音频、动画和插值的定时配置,在结构化框架上构建事件或过场动画。
- 在多个服务器之间在多个场景之间过渡,将复杂的动画和视觉效果与时间线同步。
- 浏览事件并预览体验以进行测试和开发目的。
该框架已在Roblox事件中经过实际测试,如二十一飞行员和24kGoldn音乐会,以及许多受欢迎的体验。
要在可编辑的地方查看事件序列器的实际应用,请在Roblox Studio中查看音乐会模板。此模板是开发者创建事件/音乐会并熟悉各种功能和组件的全面起点。

模块用法
安装
要在体验中使用事件序列器框架:
从Studio的窗口菜单或主页选项卡工具栏中,打开工具箱并选择创作者商店选项卡。

确保选择了模型分类,然后点击查看所有按钮以显示类别。

找到并点击包拼图。
找到事件序列器模块并点击它,或者将其拖放入3D视图中。

在资源管理器窗口中,将整个事件序列器模型移动到ServerScriptService中。在运行体验时,模块将开始运行。
框架模式
替换模式
默认框架模式是替换模式,在该模式中,您通过放置3D对象、地形、光照属性、环境效果和用户界面对象来设计独特的场景,这些对象和属性将分发到Workspace、Terrain和Lighting中,替换现有的对象/属性,以形成一个克隆空间。
内联模式
另一种框架模式是内联模式,在此模式中,您同样通过脚本逻辑为它们的流/事件设计独特的场景,但该框架不会破坏现有的3D对象、地形、光照属性、环境效果和用户界面对象,以便在加载时克隆来自场景环境文件夹的资产/属性。
要启用内联模式:
在您放置在ServerScriptService中的事件序列器模型中,向下查找并选择内联值,位于ReplicatedStorage文件夹内。

在属性窗口中,开启其值复选框。

创建场景
一个场景本质上是覆盖在一系列文件夹上的整体事件或过场动画的一部分。每个场景包含定义其流/事件的脚本逻辑,场景可以存储自己的3D对象、地形、光照属性、环境效果和用户界面对象。
要快速入手,您可以在模块的主文件夹中找到一个空场景:
展开事件序列器文件夹并找到空场景文件夹。

将整个空场景文件夹移动或复制到ReplicatedStorage。

时间长度
每个场景应具有时间长度(以秒为单位),定义其持续时长—就像电影或音乐会都有固定的持续时间。时间长度是一个数字属性,位于场景的文件夹中,命名为TimeLength,您可以在Studio中直接设置或通过Instance:SetAttribute()程序设置。


环境
场景的环境文件夹包含用户看到和听到的所有内容,包括3D对象、地形、光照属性和环境效果、以及用户界面对象。当场景加载时,这些对象和属性将被分发到Workspace、Terrain和Lighting,替换现有的对象/属性以形成一个克隆空间。
环境文件夹包含以下容器:
| 容器 | 描述 |
|---|---|
| 客户端 | 包含当任何用户(客户端)加入事件时要加载的所有资产,例如用户界面对象或动画装备。 |
| 玩家生成点 | 包含用户加入时生成的部分。此文件夹中的任何部分表现得类似于SpawnLocation。 |
| 服务器 | 包含场景首次在服务器上创建时要加载的所有资产。建议将大多数视觉资产放置在这里。 |
| 地形 | 包含场景地形。 |
| 光照 | 包含作为属性的全局光照属性,以及诸如大气效果和后期处理效果的修改器。 |
事件
场景的事件文件夹仅仅是一个占位符,用于RemoteEvents,在客户端和服务器模块之间进行通信。不是强制在此文件夹中放置任何东西。
客户端
此脚本在客户端执行架构逻辑。
服务器
此脚本在服务器执行架构逻辑。
场景架构
场景的架构定义了在场景时间线的什么时刻会发生什么。您应该在其客户端和服务器模块中定义场景的架构,并包括生命周期钩子以管理何时进行配置。
生命周期钩子
架构生命周期钩子使您能够管理场景操作发生的时间。生产中的场景通常会在最简单的流程中运行:
OnRun在查找时可能会被中断:
如果场景被重播,所有三个钩子也可以重复:
配置
架构配置定义场景的核心操作,例如在00:32播放音频、排队与该音频同步的动画、调度场景事件(例如烟花表演)等。每个配置支持某些回调函数,其中第一个参数(self)是配置实例。
寻找场景
事件序列器的一个独特功能是能够像浏览视频一样在场景之间“寻找”。在替换模式中,您还可以在场景之间切换,以预览整个多场景事件,然后将其部署到生产中。
场景寻找对所有人并不开放,因为单纯享受事件的用户不应该能够控制其时间流。相反,您必须根据事件的PlaceId以及特定的UserIds和/或组及其角色授予寻找权限。
在ServerScriptService中创建一个新的Script。
将以下代码粘贴到新脚本中。
脚本 - 设置寻找权限local ReplicatedStorage = game:GetService("ReplicatedStorage")local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))EventSequencer.setSeekingPermissions({placeIDs = {},userIDs = {},groups = {{GroupID = , MinimumRankID = },}})在setSeekingPermissions调⽤中,按如下方式填写以下表:
场景管理插件
场景管理器插件是一个实用工具,用于加载和卸载场景、光照和地形。除非您使用内联模式,否则强烈建议您使用此插件,而不是手动放置/编辑场景对象和属性。
要安装插件:
从Studio的窗口菜单或主页选项卡工具栏中,打开工具箱。
在选中的创作者商店选项卡中,从下拉菜单中选择插件。
在搜索框中输入场景管理器,然后按Enter找到此插件。

点击插件图标查看其详细信息,然后点击安装按钮。
一旦安装完成,插件将出现在Studio的插件选项卡中。
加载和卸载场景
如创建场景所述,场景的环境文件夹包含用户看到和听到的所有内容,包括3D对象。该插件帮助您快速将场景的资产入或出有组织的文件夹,放入工作区中。
| 插件操作 | 描述 |
|---|---|
| 加载客户端 | 如果场景的客户端内容被卸载,则将其环境/客户端文件夹移到工作区/场景客户端文件夹中。 |
| 加载服务器 | 如果场景的服务器内容被卸载,则将其环境/服务器文件夹移到工作区/场景服务器文件夹中。 |
| 卸载客户端 | 如果场景的客户端内容被加载,则将其客户端文件夹从工作区/场景客户端中移回到**[场景]**/环境文件夹。 |
| 卸载服务器 | 如果场景的服务器内容被加载,则将其服务器文件夹从工作区/场景服务器中移回到**[场景]**/环境文件夹。 |
| 卸载所有场景 | 将每个加载的场景的客户端和服务器文件夹移回其环境文件夹。 |
保存和加载光照
顶级Lighting服务存储了地方的所有光照属性和视觉效果。由于这是一个顶级服务,您不能手动将其移动到特定场景的环境/服务器或环境/客户端文件夹中。相反,您可以利用插件将其属性和子级复制到场景的环境/光照文件夹中。
在场景管理器插件窗口中,单击所需场景的保存光照。
保存和加载地形
由于Terrain是Workspace中的一个顶级类,因此您不能手动将生成的或雕刻的地形移动到某个特定场景的环境/服务器或环境/客户端文件夹中。相反,您可以利用插件将其复制到场景的环境/地形文件夹中。
通过顶层地形服务配置场景的地形。

在场景管理器插件窗口中,单击所需场景的保存地形。
API参考
架构生命周期钩子
OnSetup
OnSetup生命周期钩子用于初始化将在OnRun或OnEndScene中引用的资产和变量,设置用于在场景的持续时间内保持的连接等。此钩子接收timePositionObject参数,让您在设置时读取当前时间。
客户端架构
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
local Schema = EventSequencer.createSchema()
local clientEnvironment
local serverEnvironment
local dummy
Schema.OnSetup = function(timePositionObject)
print("OnSetup (客户端)")
-- 访问场景环境;不适用于内联模式
clientEnvironment = EventSequencer.getCurrentSceneEnvironment()
serverEnvironment = EventSequencer.getCurrentServerEnvironmentFromClient()
-- 等待资产
dummy = clientEnvironment:WaitForChild("Dummy")
print("当前时间是:", timePositionObject.Value)
end
服务器架构
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
local Schema = EventSequencer.createSchema()
local serverEnvironment
local partColorConnection
local changePartColorEvent = script.Parent.Events.ChangePartColor
Schema.OnSetup = function(timePositionObject)
print("OnSetup (服务器)")
-- 访问场景环境;不适用于内联模式
serverEnvironment = EventSequencer.getCurrentSceneEnvironment()
partColorConnection = changePartColorEvent.OnServerEvent:Connect(function(player, changedPart, newColor)
serverEnvironment.changedPart.Color = newColor
end)
print("当前时间是:", timePositionObject.Value)
end
OnRun
OnRun是架构中的主要操作生命周期钩子。它应该包含场景的所有定时配置,从播放音频或动画到调度事件,例如烟花表演。
客户端架构
Schema.OnRun = function()
print("OnRun (客户端)")
local MainAudio = Schema:audio({
StartTime = 1,
SoundId = "rbxassetid://1838673350",
OnStart = function(self)
print("音频播放")
end,
OnEnd = function(self)
print("音频结束")
end
})
end
OnEndScene
OnEndScene生命周期钩子用于清理场景中的任何未完成事项,例如断开在OnSetup或OnRun中创建的连接,这些连接会在场景持续期间保持。
服务器架构
Schema.OnEndScene = function()
print("OnEndScene (服务器)")
if partColorConnection then
partColorConnection:Disconnect()
partColorConnection = nil
end
end
架构配置
audio
在工作区中创建一个Sound对象,该对象在某个时刻播放。然后在场景结束后或Sound对象播放完成后,音频将被删除。
| 配置键 | 描述 |
|---|---|
| StartTime | 相对于场景持续时间,音频播放的时间(以秒为单位)。 |
| SoundId | 播放的音频的资产 ID。 |
| OnStart | 音频开始播放时触发的自定义函数。 |
| OnEnd | 音频播放完成时触发的自定义函数。 |
| Volume | Sound对象的音量;默认值为0.5。 |
客户端架构
Schema.OnRun = function()
print("OnRun (客户端)")
local MainAudio = Schema:audio({
StartTime = 1,
SoundId = "rbxassetid://1838673350",
OnStart = function(self)
print("音频播放")
end,
OnEnd = function(self)
print("音频结束")
end
})
end
animate
创建在某个时间播放的Animation。
| 配置键 | 描述 |
|---|---|
| StartTime | 相对于场景持续时间播放动画的时间(以秒为单位)。 |
| EndTime | 相对于场景持续时间结束动画的可选时间(以秒为单位)。 |
| Rig | 执行动画的动画装备。 |
| AnimationId | 要播放的动画的资产 ID。 |
| Speed | 动画的播放速度;默认值为1。 |
| FadeInTime | 动画淡入的时间(以秒为单位);默认值为0.2(秒)。 |
| FadeOutTime | 动画淡出的时间(以秒为单位);默认值为0.2(秒)。 |
| OnStart | 动画开始播放时触发的自定义函数。 |
| OnEnd | 动画播放完成时触发的自定义函数。 |
| Looped | 是否循环动画;默认值为false。 |
| SyncToAudio | 定义是否将动画与音频配置同步的表。接受以下键:
|
客户端架构
Schema.OnRun = function()
print("OnRun (客户端)")
local MainAudio = Schema:audio({
StartTime = 1,
SoundId = "rbxassetid://1838673350",
})
local DanceAnimation = Schema:animate({
AnimationId = "rbxassetid://3695333486",
Rig = Dummy,
Speed = 1,
FadeInTime = 0.1,
FadeOutTime = 0.3,
SyncToAudio = {
Audio = MainAudio,
StartAtAudioTime = 5,
},
OnStart = function(self)
print("动画播放")
end,
OnEnd = function(self)
print("动画停止")
end
})
end
tween
创建一个可配置的Tween,在寻找和动态加入时被保留,这意味着您可以在不同时间段链接插值,所有内容应按预期播放和同步。
| 配置键 | 描述 |
|---|---|
| StartTimes | 相对于场景持续时间的开始时间表(以秒为单位)。 |
| Tween | 定义要插值的对象和属性的表。接受以下键:
|
| OnStart | 插值开始时触发的自定义函数。 |
| OnHeartbeat | 每个Heartbeat上触发的自定义函数;接收插值 alpha 作为第二个参数。 |
| OnEnd | 插值完成时触发的自定义函数。 |
| SyncToAudio | 定义是否将插值与音频配置同步的表。接受以下键:
|
客户端架构
Schema.OnRun = function()
print("OnRun (客户端)")
local MainAudio = Schema:audio({
StartTime = 1,
SoundId = "rbxassetid://1838673350",
})
local LightFadeOut = Schema:tween({
StartTimes = {29.884},
Tween = {
Object = game:GetService("Lighting"),
Info = TweenInfo.new(2, Enum.EasingStyle.Sine, Enum.EasingDirection.Out),
Properties = {
Brightness = 0,
}
},
SyncToAudio = {
Audio = MainAudio,
StartAtAudioTimes = {5, 7.2, 9.4, 11.6},
},
OnStart = function(self)
print("插值播放")
end,
OnHeartbeat = function(self, alpha)
print("插值 alpha", alpha)
end,
OnEnd = function(self)
print("插值完成")
end,
})
end
interval
在指定持续时间内按指定频率(以秒为单位)执行自定义回调函数。对如闪烁灯光、脉动音频强度等重复事件非常有用。最低频率为0秒,但技术上最低频率始终被限制为Heartbeat。
| 配置键 | 描述 |
|---|---|
| StartTime | 相对于场景持续时间的间隔持续时间的开始(以秒为单位)。 |
| EndTime | 相对于场景持续时间的间隔持续时间的结束(以秒为单位)。 |
| Frequency | OnInterval函数应该触发的频率(以秒为单位),首个执行在StartTime时。 |
| OnStart | 系列间隔开始时触发的自定义函数。 |
| OnInterval | 在指定持续时间内(StartTime到EndTime)的每个间隔触发的自定义函数。 |
| OnEnd | 系列间隔结束时触发的自定义函数。 |
| SyncToAudio | 定义是否将间隔持续时间与音频配置同步的表。接受以下键:
|
客户端架构
Schema.OnRun = function()
print("OnRun (客户端)")
local MainAudio = Schema:audio({
StartTime = 1,
SoundId = "rbxassetid://1838673350",
})
local ClientTimerUpdate = Schema:interval({
Frequency = 1,
SyncToAudio = {
StartAtAudioTime = 2.5,
EndAtAudioTime = 10,
Audio = MainAudio
},
OnInterval = function(self)
print(MainAudio.Sound.TimePosition, MainAudio.CurrentSoundIntensityRatio)
end,
})
end
schedule
类似于interval,只是您可以为同一事件定义多个特定的开始时间,例如在一个场景中两次安排烟花表演。
| 配置键 | 描述 |
|---|---|
| StartTimes | 相对于场景持续时间的开始时间表(以秒为单位)。 |
| OnStart | 在StartTimes表中的每个指定时间触发的自定义函数。 |
| Skippable | 布尔值定义安排事件是否可以被晚加入的用户跳过,或者在预定开始时间前寻找时是否跳过。如果设置为false,那么所有在加入/查找时间之前安排的事件开始时间将在该加入/查找时间发生;如果设置为true,只有在加入/查找后安排的开始时间将会发生。默认值为false。 |
| SyncToAudio | 定义是否将安排与音频配置同步的表。接受以下键:
|
客户端架构
Schema.OnRun = function()
print("OnRun (客户端)")
Schema:schedule({
StartTimes = {5, 27.25},
OnStart = function(self)
-- 初始化临时心跳连接
local tempConnection = RunService.Heartbeat:Connect(function()
end)
-- 通知框架连接
Schema:inform(tempConnection)
end
})
end
inform
通知框架所有在OnRun生命周期钩子中创建的模块、UI对象、连接等,确保在寻找时正确清理它们。用例包括:
通知框架临时的临时连接,例如RunService.Heartbeat,以便在寻找早期场景的时间时清理连接。
服务器架构Schema.OnRun = function()print("OnRun (服务器)")Schema:schedule({StartTimes = {5},OnStart = function(self)-- 初始化临时心跳连接local tempConnection = RunService.Heartbeat:Connect(function()end)-- 通知框架连接Schema:inform(tempConnection)end})end在ModuleScript中调用自定义“清理”函数,该函数在OnRun生命周期钩子中初始化连接或其他引用。
服务器架构local ReplicatedStorage = game:GetService("ReplicatedStorage")local RunService = game:GetService("RunService")local customModule = require(ReplicatedStorage:WaitForChild("CustomModule"))local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))local Schema = EventSequencer.createSchema()Schema.OnRun = function()print("OnRun (服务器)")Schema:schedule({StartTimes = {5},OnStart = function(self)-- 调用自定义模块中的“init”函数customModule.init()-- 在场景清理时调用自定义模块中的“clean”函数Schema:inform(customModule, customModule.clean)end,})endModuleScript - CustomModulelocal RunService = game:GetService("RunService")local CustomModule = {}CustomModule.init = function()-- 初始化心跳连接CustomModule.connection = RunService.Heartbeat:Connect(function()end)endCustomModule.clean = function()-- 断开并清楚心跳连接if CustomModule.connection thenCustomModule.connection:Disconnect()CustomModule.connection = nilendendreturn CustomModule
函数
loadScene
loadScene(sceneName: string, startTime: number ?)
通过sceneName以编程方式加载场景,并从其开头以startTime开始。场景将有一个5秒的“宽限期”从服务器加载,然后再进行寻找和场景播放。这意味着,如果在exactly 4:15:00 PM调用loadScene("[SceneName]", 20),框架将等待额外的5秒,然后开始于4:15:25 PM。
脚本
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
-- 在当前场景完成时找出下一个要加载的场景
EventSequencer.onOrchestrationFinished:Connect(function(endedSceneName)
if endedSceneName == "PreShow" then
-- "PreShow"结束;加载音乐会中的第一个场景
EventSequencer.loadScene("Track1")
elseif endedSceneName == "Track1" then
-- "Track1"结束;加载音乐会中的第二个场景
EventSequencer.loadScene("Track2")
else
-- 循环回预演场景
EventSequencer.loadScene("PreShow")
end
end)
createSchema
createSchema(): table
返回场景架构的实例,以创建场景逻辑。
客户端架构
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
local Schema = EventSequencer.createSchema()
Schema.OnSetup = function(timePositionObject)
print("OnSetup (客户端)")
end
seek
seek(time: number)
在当前加载场景的开头,以time(以秒为单位)查找。
脚本local ReplicatedStorage = game:GetService("ReplicatedStorage")local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))EventSequencer.seek(95.58)
setSceneWarningTime
setSceneWarningTime(endSceneTimeWindow: number)
设置警告发送的时间量,从所有场景的结束开始。您可以通过onSceneEndingWarningForClient在客户端或通过onSceneEndingWarningForServer在服务器检测到警告。
脚本
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
-- 加载场景
EventSequencer.loadScene("BeautifulScene")
-- 设置警告时间为场景结束前5秒
EventSequencer.setSceneWarningTime(5)
-- 检测场景即将结束时
EventSequencer.onSceneEndingWarningForServer:Connect(function()
warn("场景即将结束!")
end)
setSeekingPermissions
setSeekingPermissions(permissions: table)
根据事件的PlaceId以及特定的UserIds和/或组及其角色授予寻找权限。有关更多信息,请参见寻找和切换场景。
getCurrentSceneEnvironment
getCurrentSceneEnvironment(): Folder (YIELDS)
根据是在客户端架构脚本还是服务器架构脚本调用,返回当前场景的客户端或服务器环境文件夹。
客户端架构
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
local Schema = EventSequencer.createSchema()
local clientEnvironment
local serverEnvironment
Schema.OnSetup = function(timePositionObject)
print("OnSetup (客户端)")
-- 访问场景环境;不适用于内联模式
clientEnvironment = EventSequencer.getCurrentSceneEnvironment()
serverEnvironment = EventSequencer.getCurrentServerEnvironmentFromClient()
print("当前时间是:", timePositionObject.Value)
end
服务器架构
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
local Schema = EventSequencer.createSchema()
local serverEnvironment
local partColorConnection
local changePartColorEvent = script.Parent.Events.ChangePartColor
Schema.OnSetup = function(timePositionObject)
print("OnSetup (服务器)")
serverEnvironment = EventSequencer.getCurrentSceneEnvironment()
partColorConnection = changePartColorEvent.OnServerEvent:Connect(function(player, changedPart, newColor)
serverEnvironment.changedPart.Color = newColor
end)
end
getCurrentServerEnvironmentFromClient
getCurrentServerEnvironmentFromClient(): Folder (YIELDS)
返回当前场景的服务器端环境文件夹。与getCurrentSceneEnvironment不同,您可以在客户端架构脚本中调用此函数。
客户端架构
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
local Schema = EventSequencer.createSchema()
local clientEnvironment
local serverEnvironment
Schema.OnSetup = function(timePositionObject)
print("OnSetup (客户端)")
-- 访问场景环境;不适用于内联模式
clientEnvironment = EventSequencer.getCurrentSceneEnvironment()
serverEnvironment = EventSequencer.getCurrentServerEnvironmentFromClient()
print("当前时间是:", timePositionObject.Value)
end
isLoadingScene
isLoadingScene(): boolean
从服务器调用,以确定场景当前是否正在加载。
脚本local ReplicatedStorage = game:GetService("ReplicatedStorage")local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))print(EventSequencer.isLoadingScene())while EventSequencer.isLoadingScene() dotask.wait()endprint("场景已加载")
事件
onSceneEndingWarningForClient
在场景即将结束之前在客户端触发。默认时间为3秒,您可以通过setSceneWarningTime进行配置。此事件只能在LocalScript中连接。
LocalScript
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
-- 检测场景即将结束(客户端)
EventSequencer.onSceneEndingWarningForClient:Connect(function()
warn("场景即将结束!")
end)
onSceneEndingWarningForServer
在场景即将结束之前在服务器触发。默认时间为3秒,您可以通过setSceneWarningTime进行配置。此事件只能在Script中连接。
脚本
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
-- 检测场景即将结束(服务器)
EventSequencer.onSceneEndingWarningForServer:Connect(function()
warn("场景即将结束!")
end)
onSceneLoadedForClient
在场景启动时触发于客户端。此事件只能在LocalScript中连接。
LocalScript
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
-- 检测场景正在启动(客户端)
EventSequencer.onSceneLoadedForClient:Connect(function()
warn("场景正在启动!")
end)
onOrchestrationFinished
在服务器上的场景已达到其时间长度并已有效结束时触发。此事件接收一个endedSceneName字符串参数,表示刚刚完成的场景,并且您可以在此事件链式条件加载另一个场景。只可以在Script中连接。
脚本
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
-- 在当前场景结束时找出下一个要加载的场景
EventSequencer.onOrchestrationFinished:Connect(function(endedSceneName)
if endedSceneName == "PreShow" then
-- "PreShow"结束;加载音乐会中的第一个场景
EventSequencer.loadScene("Track1")
elseif endedSceneName == "Track1" then
-- "Track1"结束;加载音乐会中的第二个场景
EventSequencer.loadScene("Track2")
else
-- 循环回预演场景
EventSequencer.loadScene("PreShow")
end
end)



