监视内容加载 – MRTK2

场景操作进度

加载或卸载内容时,SceneOperationInProgress 属性将返回 true。 可以通过 SceneOperationProgress 属性监视此操作的进度。

SceneOperationProgress 值是当前所有异步场景操作的平均值。 当内容加载开始时,SceneOperationProgress 将为零。 完全完成后,SceneOperationProgress 将设置为 1,并保持在 1,直到下一个操作发生。 请注意,只有内容场景操作会影响这些属性。

这些属性反映从开始到结束的整个操作的状态,即使该操作包含多个步骤:

IMixedRealitySceneSystem sceneSystem = MixedRealityToolkit.Instance.GetService<IMixedRealitySceneSystem>();

// First do an additive scene load
// SceneOperationInProgress will be true for the duration of this operation
// SceneOperationProgress will show 0-1 as it completes
await sceneSystem.LoadContent("ContentScene1");

// Now do a single scene load
// This will result in two actions back-to-back
// First "ContentScene1" will be unloaded
// Then "ContentScene2" will be loaded
// SceneOperationInProgress will be true for the duration of this operation
// SceneOperationProgress will show 0-1 as it completes
sceneSystem.LoadContent("ContentScene2", LoadSceneMode.Single)

进度示例

如果在加载内容时应挂起活动,SceneOperationInProgress 会非常有用:

public class FooManager : MonoBehaviour
{
    private void Update()
    {
        IMixedRealitySceneSystem sceneSystem = MixedRealityToolkit.Instance.GetService<IMixedRealitySceneSystem>();

        // Don't update foos while a scene operation is in progress
        if (sceneSystem.SceneOperationInProgress)
        {
            return;
        }

        // Update foos
        ...
    }
    ...
}

SceneOperationProgress 可用于显示进度对话框:

public class ProgressDialog : MonoBehaviour
{
    private void Update()
    {
        IMixedRealitySceneSystem sceneSystem = MixedRealityToolkit.Instance.GetService<IMixedRealitySceneSystem>();

        if (sceneSystem.SceneOperationInProgress)
        {
            DisplayProgressIndicator(sceneSystem.SceneOperationProgress);
        }
        else
        {
            HideProgressIndicator();
        }
    }
    ...
}

使用操作进行监视

场景系统提供了若干操作,让你能了解场景的加载和卸载情况。 每个操作都中继受影响场景的名称。

如果加载或卸载操作涉及多个场景,则会针对每个受影响的场景调用一次相关操作。 加载或卸载操作完成时,也会同时调用它们。出于此原因,建议使用 OnWillUnload 操作来检测即将销毁的内容,而不是使用 OnUnloaded 操作在事后检测销毁的内容

另一方面,因为仅当激活并完全加载所有场景时才会调用 OnLoaded 操作,使用 OnLoaded 操作来检测和使用新内容是有安全保障的

操作 调用时机 内容场景 照明场景 管理器场景
OnWillLoadContent 加载内容场景之前
OnContentLoaded 加载操作中所有内容场景完全加载并激活后
OnWillUnloadContent 内容场景卸载操作之前
OnContentUnloaded 卸载操作中所有内容场景完全卸载后
OnWillLoadLighting 照明场景加载之前
OnLightingLoaded 照明场景完全加载并激活后
OnWillUnloadLighting 照明场景卸载之前
OnLightingUnloaded 照明场景完全卸载后
OnWillLoadScene 场景加载之前
OnSceneLoaded 操作中所有场景完全加载并激活后
OnWillUnloadScene 场景卸载之前
OnSceneUnloaded 场景完全卸载后

操作示例

另一个进度对话框示例使用操作和协同例程而非更新:

public class ProgressDialog : MonoBehaviour
{
    private bool displayingProgress = false;

    private void Start()
    {
        IMixedRealitySceneSystem sceneSystem = MixedRealityToolkit.Instance.GetService<IMixedRealitySceneSystem>();
        sceneSystem.OnWillLoadContent += HandleSceneOperation;
        sceneSystem.OnWillUnloadContent += HandleSceneOperation;
    }

    private void HandleSceneOperation (string sceneName)
    {
        // This may be invoked multiple times per frame - once per scene being loaded or unloaded.
        // So filter the events appropriately.
        if (displayingProgress)
        {
            return;
        }

        displayingProgress = true;
        StartCoroutine(DisplayProgress());
    }

    private IEnumerator DisplayProgress()
    {
        IMixedRealitySceneSystem sceneSystem = MixedRealityToolkit.Instance.GetService<IMixedRealitySceneSystem>();

        while (sceneSystem.SceneOperationInProgress)
        {
            DisplayProgressIndicator(sceneSystem.SceneOperationProgress);
            yield return null;
        }

        HideProgressIndicator();
        displayingProgress = false;
    }

    ...
}

控制场景激活

默认情况下,内容场景设置为在加载时激活。 如果要手动控制场景激活,可以将 SceneActivationToken 传递到任何内容加载方法。 如果通过单个操作加载多个内容场景,则此激活令牌将应用于所有场景。

IMixedRealitySceneSystem sceneSystem = MixedRealityToolkit.Instance.GetService<IMixedRealitySceneSystem>();

SceneActivationToken activationToken = new SceneActivationToken();

// Load the content and pass the activation token
sceneSystem.LoadContent(new string[] { "ContentScene1", "ContentScene2", "ContentScene3" }, LoadSceneMode.Additive, activationToken);

// Wait until all users have joined the experience
while (!AllUsersHaveJoinedExperience())
{
    await Task.Yield();
}

// Let scene system know we're ready to activate all scenes
activationToken.AllowSceneActivation = true;

// Wait for all scenes to be fully loaded and activated
while (sceneSystem.SceneOperationInProgress)
{
    await Task.Yield();
}

// Proceed with experience

检查已加载的内容

ContentSceneNames 属性按生成索引的顺序提供一批可用的内容场景。 可通过 IsContentLoaded(string contentName) 检查这些场景是否已加载。

IMixedRealitySceneSystem sceneSystem = MixedRealityToolkit.Instance.GetService<IMixedRealitySceneSystem>();

string[] contentSceneNames = sceneSystem.ContentSceneNames;
bool[] loadStatus = new bool[contentSceneNames.Length];

for (int i = 0; i < contentSceneNames.Length; i++>)
{
    loadStatus[i] = sceneSystem.IsContentLoaded(contentSceneNames[i]);
}