场景转换服务 - MRTK2

此扩展简化了场景淡出、进度指示器显示、场景加载以及场景重新淡入的业务流程。

场景操作由 SceneSystem 服务驱动,但任何基于任务的操作都可用于驱动转换。

启用扩展

若要启用此扩展,请打开 RegisteredServiceProvider 配置文件。 单击“注册”注册新的服务提供商,以添加新配置。 在“组件类型”字段中,选择“SceneTransitionService”。 在“配置文件”字段中,选择扩展中包含的默认场景转换配置文件。

配置文件选项

使用默认进度指示器

如果选中,则在未提供进度指示器对象时调用 DoSceneTransition.,会使用默认的进度指示器预制件。如果提供了进度指示器对象,则会忽略默认值。

使用淡化颜色

如果选中,转换服务将在转换过程中应用淡化。 此设置可在运行时通过服务的 UseFadeColor 属性进行更改。

淡化颜色

控制淡化效果的颜色。 将忽略阿尔法。 此设置可在转换之前的运行时通过服务的 FadeColor 属性进行更改。

淡化目标

控制哪些摄像头将应用淡化效果。 此设置可在运行时通过服务的 FadeTargets 属性进行更改。

设置 目标摄像头
主要 将淡化效果应用于主摄像头。
UI 在 UI 层上将淡化效果应用于摄像头。 (不会影响覆盖 UI)
全部 同时应用于主摄像头和 UI 摄像头。
自定义 应用于通过 SetCustomFadeTargetCameras 提供的一组自定义摄像头

淡出时间/淡入时间

进入/退出转换的淡化持续时间的默认设置。 这些设置可在运行时通过服务的 FadeOutTimeFadeInTime 属性进行更改。

摄像头淡化程序类型

其中,ICameraFader 类用于将淡化效果应用于摄像头。 默认的 CameraFaderQuad 类在目标摄像头前面靠近裁剪平面的地方实例化一个透明材料的四边形。 另一种方法可能是使用后期效果系统。

使用扩展

可以通过传递摄像头淡出时运行的任务来使用转换服务。

使用场景系统任务

在大多数情况下,会用到 SceneSystem 服务提供的任务:

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")
        );
}

使用自定义任务

在其他情况下,可能想要在不实际加载场景的情况下执行转换:

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
}

或者,可能想要在不使用 SceneSystem 服务的情况下加载场景:

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();
    }
}

使用多个任务

还可以提供多个任务,并按顺序执行这些任务:

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;
}

使用进度指示器

进度指示器可以是实现 IProgressIndicator 接口的任何内容。 它可以采用初始屏幕、3D Tagalong 加载指示器或任何反馈转换进度的其他形式。

如果在 SceneTransitionService 配置文件中选中了 UseDefaultProgressIndicator,则在转换开始时,将实例化进度指示器。 在转换期间,可以通过该服务的 SetProgressValueSetProgressMessage 方法访问此指示器的 ProgressMessage 属性。

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();
    }
}

或者,在调用 DoSceneTransition 时,可以通过可选的 progressIndicator 参数提供自己的进度指示器。 这将覆盖默认的进度指示器。