Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Simple editor script to save and load multi-scene setups within Unity3D
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEditor.SceneManagement;
using UnityEditor;
using System.Collections;
using System.Linq;
public class MultiSceneSetup : ScriptableObject
{
public SceneSetup[] Setups;
}
public static class MultiSceneSetupMenu
{
[MenuItem("Assets/Multi Scene Setup/Create")]
public static void CreateNewSceneSetup()
{
var folderPath = TryGetSelectedFolderPathInProjectsTab();
var assetPath = ConvertFullAbsolutePathToAssetPath(
Path.Combine(folderPath, "SceneSetup.asset"));
SaveCurrentSceneSetup(assetPath);
}
[MenuItem("Assets/Multi Scene Setup/Create", true)]
public static bool CreateNewSceneSetupValidate()
{
return TryGetSelectedFolderPathInProjectsTab() != null;
}
[MenuItem("Assets/Multi Scene Setup/Overwrite")]
public static void SaveSceneSetup()
{
var assetPath = ConvertFullAbsolutePathToAssetPath(
TryGetSelectedFilePathInProjectsTab());
SaveCurrentSceneSetup(assetPath);
}
static void SaveCurrentSceneSetup(string assetPath)
{
var loader = ScriptableObject.CreateInstance<MultiSceneSetup>();
loader.Setups = EditorSceneManager.GetSceneManagerSetup();
AssetDatabase.CreateAsset(loader, assetPath);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.Log(string.Format("Scene setup '{0}' saved", Path.GetFileNameWithoutExtension(assetPath)));
}
[MenuItem("Assets/Multi Scene Setup/Load")]
public static void RestoreSceneSetup()
{
var assetPath = ConvertFullAbsolutePathToAssetPath(
TryGetSelectedFilePathInProjectsTab());
var loader = AssetDatabase.LoadAssetAtPath<MultiSceneSetup>(assetPath);
EditorSceneManager.RestoreSceneManagerSetup(loader.Setups);
Debug.Log(string.Format("Scene setup '{0}' restored", Path.GetFileNameWithoutExtension(assetPath)));
}
[MenuItem("Assets/Multi Scene Setup", true)]
public static bool SceneSetupRootValidate()
{
return HasSceneSetupFileSelected();
}
[MenuItem("Assets/Multi Scene Setup/Overwrite", true)]
public static bool SaveSceneSetupValidate()
{
return HasSceneSetupFileSelected();
}
[MenuItem("Assets/Multi Scene Setup/Load", true)]
public static bool RestoreSceneSetupValidate()
{
return HasSceneSetupFileSelected();
}
static bool HasSceneSetupFileSelected()
{
return TryGetSelectedFilePathInProjectsTab() != null;
}
static List<string> GetSelectedFilePathsInProjectsTab()
{
return GetSelectedPathsInProjectsTab()
.Where(x => File.Exists(x)).ToList();
}
static string TryGetSelectedFilePathInProjectsTab()
{
var selectedPaths = GetSelectedFilePathsInProjectsTab();
if (selectedPaths.Count == 1)
{
return selectedPaths[0];
}
return null;
}
// Returns the best guess directory in projects pane
// Useful when adding to Assets -> Create context menu
// Returns null if it can't find one
// Note that the path is relative to the Assets folder for use in AssetDatabase.GenerateUniqueAssetPath etc.
static string TryGetSelectedFolderPathInProjectsTab()
{
var selectedPaths = GetSelectedFolderPathsInProjectsTab();
if (selectedPaths.Count == 1)
{
return selectedPaths[0];
}
return null;
}
// Note that the path is relative to the Assets folder
static List<string> GetSelectedFolderPathsInProjectsTab()
{
return GetSelectedPathsInProjectsTab()
.Where(x => Directory.Exists(x)).ToList();
}
static List<string> GetSelectedPathsInProjectsTab()
{
var paths = new List<string>();
UnityEngine.Object[] selectedAssets = Selection.GetFiltered(
typeof(UnityEngine.Object), SelectionMode.Assets);
foreach (var item in selectedAssets)
{
var relativePath = AssetDatabase.GetAssetPath(item);
if (!string.IsNullOrEmpty(relativePath))
{
var fullPath = Path.GetFullPath(Path.Combine(
Application.dataPath, Path.Combine("..", relativePath)));
paths.Add(fullPath);
}
}
return paths;
}
static string ConvertFullAbsolutePathToAssetPath(string fullPath)
{
return "Assets/" + Path.GetFullPath(fullPath)
.Remove(0, Path.GetFullPath(Application.dataPath).Length + 1)
.Replace("\\", "/");
}
}
@svermeulen

This comment has been minimized.

Copy link
Owner Author

@svermeulen svermeulen commented Oct 23, 2016

Just add to an Editor/ folder in your project, and then you can right click on a folder in the Project tab and select Multi Scene Setup -> Create to save the current multi-scene setup. Or right click on an existing one then select Overwrite or Load to load it again

@tbriley

This comment has been minimized.

Copy link

@tbriley tbriley commented May 10, 2017

nice, we've been using a much crappier version of this!

@13Flo

This comment has been minimized.

Copy link

@13Flo 13Flo commented Jul 28, 2017

Very helpful. Thank you for sharing!

@ameliemaia

This comment has been minimized.

Copy link

@ameliemaia ameliemaia commented Mar 29, 2018

Very nice, thank you.

@Mathijs-Bakker

This comment has been minimized.

Copy link

@Mathijs-Bakker Mathijs-Bakker commented May 31, 2018

Very good and helpful indeed!

@c0nfused

This comment has been minimized.

Copy link

@c0nfused c0nfused commented Jan 28, 2019

in latest Unity (2018.3.3), there's a bit of a hiccup. Reproduction experience steps: Create a multiscene edit, save it via this facility, and load another scene from the project, uniquely, not in the current multiscene edit. Clicking on the saved scene setup reveals it's lost its connection to its script. Playing the newly loaded scene, and immediately stopping the play, restores that connection, and the saved scene setup now works as desired, until a another scene is loaded uniquely into the editor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.