Scene transition service — MRTK2
This extension simplifies the business of fading out a scene, displaying a progress indicator, loading a scene, then fading back in.
Scene operations are driven by the SceneSystem service, but any Task-based operation can be used to drive a transition.
Enabling the extension
To enable the extension, open your RegisteredServiceProvider profile. Click Register a new Service Provider to add a new configuration. In the Component Type field, select SceneTransitionService. In the Configuration Profile field, select the default scene transition profile included with the extension.
Profile options
Use default progress indicator
If checked, the default progress indicator prefab will be used when no progress indicator object is provided when calling DoSceneTransition.
If a progress indicator object is provided, the default will be ignored.
Use fade color
If checked, the transition service will apply a fade during your transition. This setting can be changed at runtime via the service's UseFadeColor
property.
Fade color
Controls the color of the fade effect. Alpha is ignored. This setting can be changed at runtime prior to a transition via the service's FadeColor
property.
Fade targets
Controls which cameras will have a fade effect applied to them. This setting can be changed at runtime via the service's FadeTargets
property.
Setting | Targeted Cameras |
---|---|
Main | Applies fade effect to the main camera. |
UI | Applies fade effect to cameras on the UI layer. (Does not affect overlay UI) |
All | Applies to both main and UI cameras. |
Custom | Applies to a custom set of cameras provided via SetCustomFadeTargetCameras |
Fade out time / fade in time
Default settings for the duration of a fade on entering / exiting a transition. These settings can be changed at runtime via the service's FadeOutTime
and FadeInTime
properties.
Camera fader type
Which ICameraFader
class to use for applying a fade effect to cameras. The default CameraFaderQuad
class instantiates a quad with a transparent material in front of the target camera close to the clip plane. Another approach might be to use a post effects system.
Using the extension
You use the transition service by passing Tasks that are run while the camera is faded out.
Using scene system tasks
In most cases you will be using Tasks supplied by the SceneSystem service:
private async void TransitionToScene()
{
IMixedRealitySceneSystem sceneSystem = MixedRealityToolkit.Instance.GetService<IMixedRealitySceneSystem>();
ISceneTransitionService transition = MixedRealityToolkit.Instance.GetService<ISceneTransitionService>();
// Fades out
// Runs LoadContent task
// Fades back in
await transition.DoSceneTransition(
() => sceneSystem.LoadContent("TestScene1")
);
}
Using custom tasks
In other cases you may want to perform a transition without actually loading a scene:
private async void TransitionToScene()
{
ISceneTransitionService transition = MixedRealityToolkit.Instance.GetService<ISceneTransitionService>();
// Fades out
// Resets scene
// Fades back in
await transition.DoSceneTransition(
() => ResetScene()
);
}
private async Task ResetScene()
{
// Go through all enemies in the current scene and move them back to starting positions
}
Or you may want to load a scene without using the SceneSystem service:
private async void TransitionToScene()
{
ISceneTransitionService transition = MixedRealityToolkit.Instance.GetService<ISceneTransitionService>();
// Fades out
// Loads scene using Unity's scene manager
// Fades back in
await transition.DoSceneTransition(
() => LoadScene("TestScene1")
);
}
private async Task LoadScene(string sceneName)
{
AsyncOperation asyncOp = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
while (!asyncOp.isDone)
{
await Task.Yield();
}
}
Using multiple tasks
You can also supply multiple tasks, which will be executed in order:
private async void TransitionToScene()
{
IMixedRealitySceneSystem sceneSystem = MixedRealityToolkit.Instance.GetService<IMixedRealitySceneSystem>();
ISceneTransitionService transition = MixedRealityToolkit.Instance.GetService<ISceneTransitionService>();
// Fades out
// Sets time scale to 0
// Fades out audio to 0
// Loads TestScene1
// Fades in audio to 1
// Sets time scale to 1
// Fades back in
await transition.DoSceneTransition(
() => SetTimescale(0f),
() => FadeAudio(0f, 1f),
() => sceneSystem.LoadContent("TestScene1"),
() => FadeAudio(1f, 1f),
() => SetTimescale(1f)
);
}
private async Task SetTimescale(float targetTime)
{
Time.timeScale = targetTime;
await Task.Yield();
}
private async Task FadeAudio(float targetVolume, float duration)
{
float startTime = Time.realtimeSinceStartup;
float startVolume = AudioListener.volume;
while (Time.realtimeSinceStartup < startTime + duration)
{
AudioListener.volume = Mathf.Lerp(startVolume, targetVolume, Time.realtimeSinceStartup - startTime / duration);
await Task.Yield();
}
AudioListener.volume = targetVolume;
}
Using the progress indicator
A progress indicator is anything that implements the IProgressIndicator
interface. This can take the form of a splash screen, a 3D tagalong loading indicator, or anything else that provides feedback about transition progress.
If UseDefaultProgressIndicator
is checked in the SceneTransitionService profile, a progress indicator will be instantiated when a transition begins. For the duration of the transition this indicator's Progress
and Message
properties can be accessed via that service's SetProgressValue
and SetProgressMessage
methods.
private async void TransitionToScene()
{
IMixedRealitySceneSystem sceneSystem = MixedRealityToolkit.Instance.GetService<IMixedRealitySceneSystem>();
ISceneTransitionService transition = MixedRealityToolkit.Instance.GetService<ISceneTransitionService>();
ListenToSceneTransition(sceneSystem, transition);
await transition.DoSceneTransition(
() => sceneSystem.LoadContent("TestScene1")
);
}
private async void ListenToSceneTransition(IMixedRealitySceneSystem sceneSystem, ISceneTransitionService transition)
{
transition.SetProgressMessage("Starting transition...");
while (transition.TransitionInProgress)
{
if (sceneSystem.SceneOperationInProgress)
{
transition.SetProgressMessage("Loading scene...");
transition.SetProgressValue(sceneSystem.SceneOperationProgress);
}
else
{
transition.SetProgressMessage("Finished loading scene...");
transition.SetProgressValue(1);
}
await Task.Yield();
}
}
Alternatively, when calling DoSceneTransition
you can supply your own progress indicator via the optional progressIndicator
argument. This will override the default progress indicator.