从Unity开始构建多场景,怎么样?

Con*_*sed 6 editor build unity-game-engine scene multi-scene

在Unity中进行Multiscene编辑,祝福它,允许以当前的分层状态启动(通过编辑器播放模式)当前场景.

但是,构建和运行项目无法识别编辑器中的当前场景设置,并从"构建设置"中设置的任何内容开始.

有没有办法让构建知道多场景编辑层次结构的当前编辑器状态,并构建和运行该设置?

der*_*ugo 5

1.将编辑器场景置于构建设置中

首先要收集设置,您可以使用编辑器脚本

表1.A 更新MenuItem单击

我把它作为菜单中的一个额外按钮,因为你可能不想总是自动拥有它.

using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.SceneManagement;

public static class UpdateBuildSettigns
{
    [MenuItem("Example/UpdateBuildSettings")]
    public static void UpdateSettings()
    {
        // get current editor setup
        SceneSetup[] editorScenes = EditorSceneManager.GetSceneManagerSetup();

        // filter list e.g. get only scenes with isActive true
        var activeEditorScenes = editorScenes.Where(scene => scene.isLoaded);

        // set those scenes as the buildsettings
        List<EditorBuildSettingsScene> editorBuildSettingsScenes = new List<EditorBuildSettingsScene>();
        foreach (var sceneAsset in activeEditorScenes)
        {
            string scenePath = sceneAsset.path;

            // ignore unsaved scenes
            if (!string.IsNullOrEmpty(scenePath)) continue;

            editorBuildSettingsScenes.Add(new EditorBuildSettingsScene(scenePath, true));
        }

        // Set the Build Settings window Scene list
        EditorBuildSettings.scenes = editorBuildSettingsScenes.ToArray();
    }
}
Run Code Online (Sandbox Code Playgroud)

更新菜单按钮

在此输入图像描述


1.B. 自动更新(非)加载场景

如果您希望它自动发生,您还可以使用InitializeOnLoad和静态构造函数将调用作为回调添加到EditorSceneManager.sceneOpenedEditorSceneManager.sceneClosed,以便在重新编译或打开UnityEditor之后添加回调

using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine.SceneManagement;

[InitializeOnLoad]
public static class UpdateBuildSettigns
{
    // ofcourse you still can also call it via menu item
    [MenuItem("Example/UpdateBuildSettings")]
    public static void UpdateSettings()
    {
        //...
    }

    static UpdateBuildSettigns()
    {
        // it is always save to remove callbacks even if they are not there
        // makes sure they are always only added once
        //
        // this is a static constructor so actually there should be no
        // callbacks yet ... but .. you never know ;)
        EditorSceneManager.sceneOpened -= OnSceneLoaded;
        EditorSceneManager.sceneClosed -= OnSceneUnloaded;

        EditorSceneManager.sceneOpened += OnSceneLoaded;
        EditorSceneManager.sceneClosed += OnSceneUnloaded;
    }

    private static void OnSceneUnloaded(Scene current)
    {
        UpdateSettings();
    }

    private static void OnSceneLoaded(Scene current, OpenSceneMode mode)
    {
        UpdateSettings();
    }
}
Run Code Online (Sandbox Code Playgroud)

使用自动更新

在此输入图像描述


1.C. 启用/禁用自动更新

如果您想要更多控制,您还可以添加额外的菜单条目,以启用和禁用自动更新等

// flag to check if auto-updates are currently enabled
private static bool isEnabled;

// disable the "EnableAutoUpdate" button if already enabled
[MenuItem("Example/EnableAutoUpdate", true)]
private static bool CanEnable()
{
    return !isEnabled;
}

// disable the "DisableAutoUpdate" button if already disabled
[MenuItem("Example/DisableAutoUpdate", true)]
private static bool CanDisable()
{
    return isEnabled;
}

// add callbacks
[MenuItem("Example/EnableAutoUpdate")]
private static void EnableAutoUpdate()
{
    // it is always save to remove callbacks even if they are not there
    // makes sure they are always only added once
    EditorSceneManager.sceneOpened -= OnSceneLoaded;
    EditorSceneManager.sceneClosed -= OnSceneUnloaded;

    EditorSceneManager.sceneOpened += OnSceneLoaded;
    EditorSceneManager.sceneClosed += OnSceneUnloaded;

    isEnabled = true;
}

// remove callbacks
[MenuItem("Example/DisableAutoUpdate")]
private static void DisableAutoUpdate()
{
    EditorSceneManager.sceneOpened -= OnSceneLoaded;
    EditorSceneManager.sceneClosed -= OnSceneUnloaded;

    isEnabled = false;
}
Run Code Online (Sandbox Code Playgroud)

请注意,因为它使用UnityEditor命名空间,您应该将此脚本放在一个Editor文件夹中或使用适当的预处理器

#if UNITY_EDITOR

// above code here

#endif
Run Code Online (Sandbox Code Playgroud)

2.从构建设置加载所有场景

比以后在第一个场景中运行应用程序时,应该有一个脚本负责加载所有这些场景.像是这样的东西

// making it a component to make sure it is inside of one scene
public class SceneLoader : MonoBehaviour
{
    private void Start()
    {
        var thisScene = SceneManager.GetActiveScene();

        // load all scenes
        for(int i = 0; i < SceneManager.sceneCountInBuildSettings; i++)
        {
            // skip if is current scene since we don't want it twice
            if(thisScene.buildIndex == i) continue;

             // Skip if scene is already loaded
            if(SceneManager.GetSceneByBuildIndex(i).IsValid()) continue;

            SceneManager.LoadScene(i, LoadSceneMode.Additive);
            // or depending on your usecase
            SceneManager.LoadSceneAsync(i, LoadSceneMode.Additive);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

裁判: