EventSequencer는 구조화된 액션 및 트리거 시퀀스에서 라이브, 크로스 서버 이벤트, 컷씬을 구축하는 강력한 프레임워크입니다. 보다 구체적으로, 해당 모듈은 다음 사항을 지원합니다.
- 오디오, 애니메이션, 트윈의 예정 구성을 통해 구조화 프레임워크에서 이벤트 또는 컷씬 구축.
- 다중 서버에 걸쳐 다중 씬들을 상호 전환하여 복잡한 애니메이션 및 시각적 요소를 타임라인에 동기화.
- 테스트 및 개발 목적의 이벤트 탐색 및 체험 사전 시연.
이 프레임워크는 Twenty One Pilots 및 24kGoldn 콘서트와 같은 Roblox 이벤트와 방문 수가 높은 체험에서 실전 테스트를 거쳤습니다.
편집 가능한 플레이스 내에서 작업의 EventSequencer를 보려면, Roblox Studio에서 콘서트 템플릿을 선택하십시오. 이러한 템플릿은 개발자가 이벤트/콘서트를 제작하고, 다양한 관련 기능 및 구성 요소에 익숙해지게 하는 포괄적인 출발점입니다.
모듈 사용
설치
체험에서 EventSequencer 프레임워크를 사용하는 방법:
보기 탭에서 도구 상자를 열고 마켓플레이스 탭을 선택합니다.
모델 정렬이 선택되었는지 확인한 다음 카테고리에서 모두 보기 버튼을 클릭합니다.
DEV MODULES 타일을 찾아 클릭합니다.
Event Sequencer 모듈을 찾아 클릭하거나 3D 보기로 끌어다 놓습니다.
탐색기 창에서 전체 EventSequencer 모델을 ServerScriptService로 이동시킵니다. 체험을 실행하면 모듈이 다양한 서비스에 배포되고 실행되기 시작합니다.
프레임워크 모드
교체 모드
기본 프레임워크 모드는 3D 개체, 지형, 조명 속성, 환경 효과 및 사용자 인터페이스 개체를 해당 씬의 Environment 폴더에 배치하여 고유 씬을 디자인하는 교체 모드입니다. 씬을 로딩하면 해당 개체 및 속성이 Workspace, Terrain 및 Lighting(으)로 분산되어 기존 개체/속성을 대체하여 복제 공간을 형성합니다.
인라인 모드
대체 프레임워크 모드는 흐름/이벤트에 대한 스크립팅 논리를 사용하여 고유 씬을 유사하게 디자인하는 인라인 모드이지만, 이러한 프레임워크는 로딩할 때 씬의 Environment 폴더에서 자산/속성을 복제하기 위해 기존 3D 개체, 지형, 조명 속성, 환경 효과 및 사용자 인터페이스 개체를 파괴하지 않습니다.
인라인 모드를 활성화하는 방법:
ServerScriptService에 있는 EventSequencer 폴더를 드릴 다운하여 ReplicatedStorage 폴더 내에서 인라인 값을 선택합니다.
속성 창에서 해당 값 체크박스를 체크합니다.
씬 만들기
씬은 기본적으로 전체 이벤트의 일부이거나 일련의 폴더로 묶인 컷씬입니다. 각 씬에는 흐름/이벤트를 정의하는 스크립팅 논리가 포함되어 있으며, 여기에는 자체 3D 개체, 지형, 조명 속성, 환경 효과, 사용자 인터페이스 개체를 저장할 수 있습니다.
빠르게 시작하려면 모듈의 기본 폴더 내에서 비어 있는 씬을 찾으십시오.
EventSequencer 폴더를 확장하고 BlankScene 폴더를 찾습니다.
전체 BlankScene 폴더를 ReplicatedStorage로 이동시키나 복사합니다.
시간 길이
영화나 콘서트에 설정된 길이가 있는 것처럼 각 씬에는 시간 길이(초 단위)가 정해져야 합니다. 시간 길이는 Studio에서 직접 설정하거나 Instance:SetAttribute()을(를) 통해 프로그래밍 방식으로 설정할 수 있으며, 이는 TimeLength라는 씬 폴더의 숫자 속성으로 정의됩니다.
환경
씬의 Environment 폴더에는 3D 개체, 지형, 조명 속성, 환경 효과, 사용자 인터페이스 개체 등을 포함하여 사용자가 보고 듣는 모든 것이 포함됩니다. 씬을 로딩하면 해당 개체 및 속성이 ,Workspace Terrain및 (Lighting으)로 분산되어 기존 개체/속성을 대체하여 복제 공간을 형성합니다.
Environment 폴더에는 다음과 같은 컨테이너가 포함되어 있습니다.
컨테이너 | 설명 |
---|---|
Client | 사용자 인터페이스 개체 또는 애니메이션 장비와 같이, 사용자(클라이언트)가 이벤트에 참여할 때 로딩할 전체 자산이 포함됩니다. |
PlayerSpawns | 사용자 참여 시 생성되는 부분이 포함됩니다. 해당 폴더의 모든 부분은 SpawnLocation와(과) 유사하게 작동합니다. |
Server | 씬이 서버에서 처음 생성될 때 로딩하는 전체 자산이 포함됩니다. 대부분의 시각적 자산을 해당 항목에 배치하는 것이 좋습니다. |
Terrain | 씬 지형을 포함합니다. |
Lighting | 전역 조명 속성이 속성으로서 포함되고 대기 효과 및 후처리 효과와 같은 수정자가 포함됩니다. |
이벤트
씬의 Events 폴더는 순전히 Client및 Serve 모듈 간 의사소통을 위한 RemoteEvents의 플레이스 표시자입니다. 해당 폴더에 아무 것도 배치할 필요가 없습니다.
클라이언트
해당 스크립트는 클라이언트에서 스키마 논리를 실행합니다.
서버
해당 스크립트는 서버에서 스키마 논리를 실행합니다.
씬 스키마
씬 스키마는 씬 타임라인의 어떤 지점에서 발생하는 사건을 정의합니다. Client 및 Server 모듈 모두에서 씬의 스키마를 정의하고, 구성이 발생할 때 관리할 라이프 사이클 후크를 포함시켜야 합니다.
라이프 사이클 후크
스키마 라이프 사이클 후크를 사용하면 씬 작업이 발생하는 시점을 관리할 수 있습니다. 프로덕션 씬은 일반적으로 가장 간단한 흐름으로 실행됩니다.
다음을 탐색할 때 OnRun이 중단될 수 있습니다.
씬이 재생되는 경우 세 후크 모두 반복됩니다.
구성
스키마 구성은 씬의 핵심 작업을 정의합니다. 예를 들어 32초 시점에 오디오를 재생하고, 해당 오디오와 동기화된 애니메이션 재생을 대기시키거나, 불꽃놀이와 같은 씬 이벤트 예약을 수행할 수 있습니다. 모든 구성은 첫 번째 매개 변수(self)가 구성 인스턴스인 특정 콜백 함수를 지원합니다.
씬 찾기
EventSequencer의 고유 기능은 비디오를 통한 탐색처럼, 씬 주변을 '탐색하는' 기능입니다. 전체 다중 씬 이벤트를 프로덕션에 배포하기 전에 이를 미리 보기 위해 Replace Mode에서 씬을 상호 전환할 수도 있습니다.
단순히 이벤트를 즐기는 사용자는 시간 흐름을 제어하지 못해야 하므로, 씬 탐색에 모든 사람이 액세스할 수는 없습니다. 대신 이벤트와 이벤트 내 PlaceId 뿐만 아니라, 특정 UserIds 또는 그룹 및 역할을 기반으로 탐색 권한을 부여해야 합니다.
ServerScriptService 안에 새로운 Script을(를) 만듭니다.
새로운 스크립트에 다음의 코드를 붙여 넣습니다.
Script - Set Seeking Permissionslocal ReplicatedStorage = game:GetService("ReplicatedStorage")local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))EventSequencer.setSeekingPermissions({placeIDs = {},userIDs = {},groups = {{GroupID = , MinimumRankID = },}})setSeekingPermissions 호출 내에서 다음 테이블을 다음과 같이 채우십시오.
placeIDs | 내부 탐색을 지원하는 PlaceId 값을 쉼표로 구분한 목록입니다. |
userIDs | 지원되는 플레이스 내에서 탐색이 가능한 사용자의 UserId값을 쉼표로 구분한 목록입니다. |
groups | 쉼표로 구분한 테이블 목록으로서, 각각 그룹 ID와 지원되는 플레이스 내에서 탐색이 가능한 해당 그룹 구성원의 최소 순위를 포함합니다. |
씬 관리자 플러그인
씬 관리자 플러그인은 씬, 조명 및 지형을 로딩 및 언로딩하는 데 유용한 도구입니다. 인라인 모드를 사용하지 않는다면, 씬 개체 및 속성을 수동으로 배치/편집하는 대신 해당 플러그인을 사용하는 것이 좋습니다.
플러그인을 설치하는 방법:
Studio의 보기 메뉴에서 도구 상자를 엽니다.
Marketplace 탭을 선택한 상태에서 드롭다운 메뉴에서 Plugins를 선택합니다.
검색창에 씬 관리자를 입력하고 Enter 키를 눌러 플러그인을 찾습니다.
플러그인의 아이콘을 클릭하여 세부 정보를 확인한 다음, 파란색 Install 버튼을 클릭합니다.
플러그인이 설치되면 Studio의 Plugins 탭에 해당 항목이 나타납니다.
씬 로딩 및 언로딩
씬 만들기에 설명된 대로, 씬의 Environment 폴더에는 3D 개체를 포함하여 사용자가 보고 듣는 모든 것이 포함됩니다. 플러그인을 사용하면 작업 영역 내의 정리된 폴더 안팎으로 씬의 자산을 빠르게 로딩할 수 있습니다.
플러그인 동작 | 설명 |
---|---|
클라이언트 로드 | 씬의 클라이언트 콘텐츠가 언로딩되면, 해당 Environment/Client 폴더를 Workspace/ScenesClient 폴더로 이동시킵니다. |
서버 로드 | 씬의 서버 콘텐츠가 언로딩되면 Environment/Server 폴더를 Workspace/ScenesServer 폴더로 이동시킵니다. |
클라이언트 언로드 | 씬의 클라이언트 콘텐츠가 로딩되면, 해당 Client 폴더를 Workspace/ScenesClient에서 다시 [Scene]/Environment 폴더로 이동시킵니다. |
서버 언로드 | 씬의 서버 콘텐츠가 로딩되면 해당 Server 폴더를 Workspace/ScenesServer에서 다시 [Scene]/Environment 폴더로 이동시킵니다. |
모든 씬 언로드 | 로딩된 모든 씬의 Client 및 Server 폴더를 다시 해당 Environment 폴더로 이동시킵니다. |
조명 저장 및 로딩
최상위 Lighting 서비스는 플레이스의 전체 조명 속성과 시각 효과를 저장합니다. 이는 최상위 서비스이므로, 이를 특정 씬의 Environment/Server 또는 Environment/Client 폴더로 수동 이동시킬 수 없습니다. 대신 플러그인을 활용하여 해당 속성과 자식 개체를 씬의 환경/조명 폴더에 복사할 수 있습니다.
씬 관리자 플러그인 창에서 원하는 씬에 조명 저장을 클릭합니다.
해당 프레임워크는 Twenty One Pilots 및 24kGoldn 콘서트 등의 Roblox 이벤트와 방문자 수가 많은 여러 체험에서 실전 테스트를 거쳤습니다.
지형 저장 및 로딩
Terrain은(는) Workspace 내의 최상위 클래스이므로, 생성되거나 조형된 지형을 특정 씬의 Environment/Server 또는 Environment/Client 폴더로 수동으로 이동할 수 없습니다. 대신, 플러그인을 활용하여 씬의 환경/지형 폴더에 복사할 수 있습니다.
최상위 Terrain 서비스를 통해 씬의 지형을 구성합니다.
씬 관리자 플러그인 창에서 원하는 씬에 지형 저장을 클릭합니다.
해당 씬의 환경/지형 폴더를 선택하고 확장하면 저장된 지형을 나타내는 TerrainRegion 개체가 표시됩니다.
씬의 지형이 저장되면 플러그인 창에서 **지형 로딩을 **클릭하여 최상위 레벨 Terrain 서비스로 빠르게 다시 로딩할 수 있습니다.
API 참조
스키마 라이프 사이클 후크
OnSetup
OnSetup 라이프 사이클 후크는 OnRun 또는 OnEndScene에서 참조할 자산 및 변수를 초기화하고, 씬이 동안 지속되도록 의도된 connections을(를) 설정하는 등의 용도로 사용됩니다. 이러한 후크는 설정 시 현재 시간을 읽을 수 있게 하는 timePositionObject 매개 변수를 받습니다.
Client Schema
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 (Client)")
-- Access scene environments; does not apply to Inline Mode
clientEnvironment = EventSequencer.getCurrentSceneEnvironment()
serverEnvironment = EventSequencer.getCurrentServerEnvironmentFromClient()
-- Wait for assets
dummy = clientEnvironment:WaitForChild("Dummy")
print("Current time is:", timePositionObject.Value)
end
Server Schema
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 (Server)")
-- Access scene environment; does not apply to Inline Mode
serverEnvironment = EventSequencer.getCurrentSceneEnvironment()
partColorConnection = changePartColorEvent.OnServerEvent:Connect(function(player, changedPart, newColor)
serverEnvironment.changedPart.Color = newColor
end)
print("Current time is:", timePositionObject.Value)
end
OnRun
OnRun은 스키마 내의 주된 운영 라이프 사이클 후크입니다. 여기에는 오디오 또는 애니메이션 재생이나 불꽃놀이 등의 이벤트 예약까지 씬에 대한 전체 시간 구성이 포함되어야 합니다.
Client Schema
Schema.OnRun = function()
print("OnRun (Client)")
local MainAudio = Schema:audio({
StartTime = 1,
SoundId = "rbxassetid://1838673350",
OnStart = function(self)
print("Audio playing")
end,
OnEnd = function(self)
print("Audio ended")
end
})
end
OnEndScene
OnEndScene 라이프 사이클 후크는 씬이 지속되는 동안 남아 있는 OnSetup 또는 OnRun에서 생성된 연결을 끊는 등, 씬에서 미해결 항목을 정리하는 데 유용합니다.
Server Schema
Schema.OnEndScene = function()
print("OnEndScene (Server)")
if partColorConnection then
partColorConnection:Disconnect()
partColorConnection = nil
end
end
스키마 구성
오디오
작업 공간에 특정 시간에 재생되는 Sound 개체를 만듭니다. 이후에는 씬이 끝난 후 또는 Sound 개체 재생이 끝난 후에 사운드가 삭제됩니다.
구성 키 | 설명 |
---|---|
StartTime | 씬 지속과 관련하여 오디오를 재생하는 시점(초 단위). |
SoundId | 재생할 오디오의 자산 ID. |
OnStart | 오디오 재생이 시작될 때 실행되는 사용자 지정 함수. |
OnEnd | 오디오 재생이 끝나면 실행되는 사용자 지정 함수. |
Volume | Sound 개체의 부피. 기본값은 0.5입니다. |
Client Schema
Schema.OnRun = function()
print("OnRun (Client)")
local MainAudio = Schema:audio({
StartTime = 1,
SoundId = "rbxassetid://1838673350",
OnStart = function(self)
print("Audio playing")
end,
OnEnd = function(self)
print("Audio ended")
end
})
end
애니메이션 만들기
특정 시간에 재생되는 Animation을(를) 만듭니다.
구성 키 | 설명 |
---|---|
StartTime | 씬 지속과 관련하여 애니메이션을 재생하는 시점(초 단위). |
EndTime | 씬 지속과 관련하여 애니메이션을 종료할 선택적 시간(초 단위). |
Rig | 애니메이션을 재생할 애니메이션 리그. |
AnimationId | 재생할 애니메이션의 자산 ID. |
Speed | 애니메이션의 재생 속도. 기본값은 1입니다. |
FadeInTime | 애니메이션을 페이드 인하는 데 걸리는 시간(초 단위). 기본값은 0.2(초 단위)입니다. |
FadeOutTime | 애니메이션을 페이드 아웃하는 데 걸리는 시간(초 단위). 기본값은 0.2(초 단위)입니다. |
OnStart | 애니메이션 재생이 시작될 때 실행되는 사용자 지정 함수. |
OnEnd | 애니메이션 재생이 끝나면 실행되는 사용자 지정 함수. |
Looped | 애니메이션 반복 여부. 기본값은 false입니다. |
SyncToAudio | 애니메이션을 오디오 구성과 동기화할지 여부를 정의하는 테이블. 다음 키를 수락합니다.
|
Client Schema
Schema.OnRun = function()
print("OnRun (Client)")
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("Animation playing")
end,
OnEnd = function(self)
print("Animation stopped")
end
})
end
tween
검색 및 동적 결합에서 보존되는 구성 가능한 Tween을(를) 생성합니다. 즉, 별도의 시점에 트윈을 연결할 수 있으며, 모든 것이 예상대로 재생 및 동기화되어야 합니다.
구성 키 | 설명 |
---|---|
StartTimes | 씬 지속과 관련된 시작 시간 표(초 단위). |
Tween | 트윈할 개체 및 속성을 정의하는 테이블. 다음 키를 수락합니다.
|
OnStart | 트윈 재생이 시작될 때 실행되는 사용자 지정 함수. |
OnHeartbeat | 모든 Heartbeat에서 실행하는 사용자 지정 함수, 트윈 알파를 두 번째 매개 변수로 받습니다. |
OnEnd | 트윈 재생이 끝나면 실행되는 사용자 지정 함수. |
SyncToAudio | 트윈을 오디오 구성에 동기화할지 여부를 정의하는 테이블. 다음 키를 수락합니다.
|
Client Schema
Schema.OnRun = function()
print("OnRun (Client)")
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("Tween playing")
end,
OnHeartbeat = function(self, alpha)
print("Tween alpha", alpha)
end,
OnEnd = function(self)
print("Tween completed")
end,
})
end
interval
지정된 빈도(초 단위)로 지정된 기간 동안 사용자 지정 콜백 함수를 실행합니다. 번쩍이는 불빛, 오디오 강도 펄스 등의 반복 이벤트에 유용합니다. 가능한 가장 낮은 주파수는 0초이지만, 기술적으로 최소 주파수는 항상 Heartbeat(으)로 고정됩니다.
구성 키 | 설명 |
---|---|
StartTime | 씬 지속 시간과 관련된 간격 지속 시간의 시작(초 단위). |
EndTime | 씬 지속 시간과 관련된 간격 지속 시간의 끝(초 단위). |
Frequency | StartTime에서 첫 번째 실행이 있을 때 OnInterval 함수가 실행되는 빈도(초 단위). |
OnStart | 일련의 인터벌이 시작될 때 실행되는 사용자 지정 함수. |
OnInterval | 지정된 기간(StartTime에서 EndTime까지) 내의 모든 인터벌으로 실행되는 사용자 지정 기능. |
OnEnd | 일련의 인터벌이 종료될 때 실행되는 사용자 지정 함수. |
SyncToAudio | 인터벌 기간을 오디오 구성과 동기화할지 여부를 정의하는 테이블. 다음 키를 수락합니다.
|
Client Schema
Schema.OnRun = function()
print("OnRun (Client)")
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
스케줄
이는 한 씬에서 불꽃놀이를 두 번 예약하는 등, 동일한 이벤트에 대해 다수의 특정 시작 시간을 정의할 수 있다는 점을 제외하면 인터벌과 비슷합니다.
구성 키 | 설명 |
---|---|
StartTimes | 씬 지속과 관련된 시작 시간 표(초 단위). |
OnStart | StartTimes 테이블에서 지정된 시간마다 실행하는 사용자 지정 함수. |
Skippable | 늦게 참여하는 사용자에 대해 또는 예약된 시작 시간 이전에 검색할 때, 예약된 이벤트를 건너뛸 수 있는지 여부를 정의하는 부울. false(으)로 설정하면 참여/탐색 시간 이전에 예약된 전체 이벤트 시작 시간이 해당 참여/탐색 시간에 발생합니다. true(으)로 설정하면 참여/탐색 이후 예약된 시작 시간만 발생합니다. 기본값은 false입니다. |
SyncToAudio | 예약을 오디오 구성과 동기화할지 여부를 정의하는 테이블. 다음 키를 수락합니다.
|
Client Schema
Schema.OnRun = function()
print("OnRun (Client)")
Schema:schedule({
StartTimes = {5, 27.25},
OnStart = function(self)
-- Initialize temporary heartbeat connection
local tempConnection = RunService.Heartbeat:Connect(function()
end)
-- Inform framework of connection
Schema:inform(tempConnection)
end
})
end
통보
OnRun 라이프 사이클 후크에서 생성된 모든 모듈, UI 개체, 연결 등을 프레임워크에 통보하고 검색 시 적절하게 정리되도록 합니다. 사용 사례:
씬 지속의 이전 지점을 찾을 때 연결이 정리되도록 프레임워크에 RunService.Heartbeat와(과) 같은 임시 특별 연결을 통보합니다.
Server SchemaSchema.OnRun = function()print("OnRun (Server)")Schema:schedule({StartTimes = {5},OnStart = function(self)-- Initialize temporary heartbeat connectionlocal tempConnection = RunService.Heartbeat:Connect(function()end)-- Inform framework of connectionSchema:inform(tempConnection)end})endOnRun 라이프 사이클 후크 동안 연결 또는 기타 참조를 초기화하는 ModuleScript에서 사용자 지정 '정리' 함수 호출.
Server Schemalocal 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 (Server)")Schema:schedule({StartTimes = {5},OnStart = function(self)-- Call "init" function in custom modulecustomModule.init()-- Call "clean" function in custom module on scene cleanupSchema:inform(customModule, customModule.clean)end,})endModuleScript - CustomModulelocal RunService = game:GetService("RunService")local CustomModule = {}CustomModule.init = function()-- Initialize heartbeat connectionCustomModule.connection = RunService.Heartbeat:Connect(function()end)endCustomModule.clean = function()-- Disconnect and clear heartbeat connectionif CustomModule.connection thenCustomModule.connection:Disconnect()CustomModule.connection = nilendendreturn CustomModule
함수
loadScene
loadScene(sceneName:string, startTime:number?)
프로그래밍 방식의 sceneName(으)로 씬을 로딩하고 처음부터 startTime에서 시작합니다. 검색이 발생하고 씬 재생이 시작되기 전에 서버에서 씬을 로딩하는 데 5초의 '유예 기간'이 있습니다. 즉, 정확히 오후 4시 15분에 loadScene("[SceneName]", 20)을(를) 호출하면 프레임워크는 요청된 20초 외에 5초를 대기하여 오후 4시 15분 25초에 씬을 시작합니다.
Script
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
-- Figure out next scene to load when current scene finishes
EventSequencer.onOrchestrationFinished:Connect(function(endedSceneName)
if endedSceneName == "PreShow" then
-- "PreShow" ended; load the first scene in the concert
EventSequencer.loadScene("Track1")
elseif endedSceneName == "Track1" then
-- "Track1" ended; load the second scene in the concert
EventSequencer.loadScene("Track2")
else
-- Loop back to the pre-show scene
EventSequencer.loadScene("PreShow")
end
end)
createSchema
createSchema():table
씬의 논리를 만들기 위해 씬 스키마의 인스턴스를 반환합니다.
Client Schema
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
local Schema = EventSequencer.createSchema()
Schema.OnSetup = function(timePositionObject)
print("OnSetup (Client)")
end
탐색
seek(time:number)
현재 불러온 씬의 시작 부분에서 초 단위로 time 값을 찾습니다.
Script
local ReplicatedStorage = game:GetService("ReplicatedStorage")local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))EventSequencer.seek(95.58)
setSceneWarningTime
setSceneWarningTime(endSceneTimeWindow:number)
전체 씬이 종료된 후 경고가 발송되는 시간을 설정합니다. onSceneEndingWarningForClient를 통해 클라이언트 측에서 또는 onSceneEndingWarningForServer를 통해 서버 측에서 경고를 감지할 수 있습니다.
Script
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
-- Load scene
EventSequencer.loadScene("BeautifulScene")
-- Set warning time to 5 seconds before the scene ends
EventSequencer.setSceneWarningTime(5)
-- Detect when scene is about to end
EventSequencer.onSceneEndingWarningForServer:Connect(function()
warn("Scene is about to end!")
end)
setSeekingPermissions
setSeekingPermissions(permissions:table)
이벤트의 PlaceId뿐만 아니라, 특정 UserIds 또는 그룹 및 그 내의 역할을 기반으로 요청 권한을 부여합니다. 자세한 내용은 씬 찾기 및 전환을 참조하십시오.
getCurrentSceneEnvironment
getCurrentSceneEnvironment():Folder YIELDS
각각 Client 스키마 스크립트 또는 Server 스키마 스크립트에서 호출되었는지 여부에 따라 현재 씬의 클라이언트 측 또는 서버 측 Environment 폴더를 반환합니다.
Client Schema
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 (Client)")
-- Access scene environments; does not apply to Inline Mode
clientEnvironment = EventSequencer.getCurrentSceneEnvironment()
serverEnvironment = EventSequencer.getCurrentServerEnvironmentFromClient()
print("Current time is:", timePositionObject.Value)
end
Server Schema
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 (Server)")
serverEnvironment = EventSequencer.getCurrentSceneEnvironment()
partColorConnection = changePartColorEvent.OnServerEvent:Connect(function(player, changedPart, newColor)
serverEnvironment.changedPart.Color = newColor
end)
end
getCurrentServerEnvironmentFromClient
getCurrentServerEnvironmentFromClient():Folder YIELDS
현재 씬의 서버측 Environment 폴더를 반환합니다. getCurrentSceneEnvironment와 달리 클라이언트 스키마 스크립트에서 호출할 수 있습니다.
Client Schema
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 (Client)")
-- Access scene environments; does not apply to Inline Mode
clientEnvironment = EventSequencer.getCurrentSceneEnvironment()
serverEnvironment = EventSequencer.getCurrentServerEnvironmentFromClient()
print("Current time is:", timePositionObject.Value)
end
isLoadingScene
isLoadingScene():boolean
씬을 현재 로딩하고 있는지 확인하기 위해 서버에서 호출됩니다.
Script
local ReplicatedStorage = game:GetService("ReplicatedStorage")local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))print(EventSequencer.isLoadingScene())while EventSequencer.isLoadingScene() dotask.wait()endprint("Scene loaded")
이벤트
onSceneEndingWarningForClient
onSceneEndingWarningForClient(): RBXScriptSignal
씬이 끝나기 전에 클라이언트에서 실행됩니다. 기본 시간은 3초이지만 setSceneWarningTime을 통해 설정할 수 있습니다. 해당 이벤트는 LocalScript에서만 연결할 수 있습니다.
LocalScript
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
-- Detect when scene is about to end (client-side)
EventSequencer.onSceneEndingWarningForClient:Connect(function()
warn("Scene is about to end!")
end)
onSceneEndingWarningForServer
onSceneEndingWarningForServer(): RBXScriptSignal
씬이 끝나기 전에 서버에서 실행됩니다. 기본 시간은 3초이지만 setSceneWarningTime을 통해 설정할 수 있습니다. 해당 이벤트는 Script에서만 연결할 수 있습니다.
Script
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
-- Detect when scene is about to end (server-side)
EventSequencer.onSceneEndingWarningForServer:Connect(function()
warn("Scene is about to end!")
end)
onSceneLoadedForClient
onSceneLoadedForClient(): RBXScriptSignal
씬이 시작될 때 클라이언트에서 실행됩니다. 해당 이벤트는 LocalScript에서만 연결할 수 있습니다.
LocalScript
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
-- Detect when scene is starting (client-side)
EventSequencer.onSceneLoadedForClient:Connect(function()
warn("Scene is starting!")
end)
onOrchestrationFinished
onOrchestrationFinished(): RBXScriptSignal
씬이 정해진 시간 길이에 도달하고 효과적으로 종료되면 서버에서 실행됩니다. 해당 이벤트는 방금 완료된 씬에 대한 endedSceneName 문자열 이름 인수를 수신하며, 해당 이벤트를 연결하여 다른 씬을 조건부로 로드할 수 있습니다. Script에만 연결할 수 있습니다.
Script
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EventSequencer = require(ReplicatedStorage:WaitForChild("EventSequencer"))
-- Figure out next scene to load when current scene finishes
EventSequencer.onOrchestrationFinished:Connect(function(endedSceneName)
if endedSceneName == "PreShow" then
-- "PreShow" ended; load the first scene in the concert
EventSequencer.loadScene("Track1")
elseif endedSceneName == "Track1" then
-- "Track1" ended; load the second scene in the concert
EventSequencer.loadScene("Track2")
else
-- Loop back to the pre-show scene
EventSequencer.loadScene("PreShow")
end
end)