Skip to content

Instantly share code, notes, and snippets.

@wtrebella
Last active April 28, 2025 22:06
Show Gist options
  • Save wtrebella/671b4dff339be37cc11bd302461bc159 to your computer and use it in GitHub Desktop.
Save wtrebella/671b4dff339be37cc11bd302461bc159 to your computer and use it in GitHub Desktop.
Scene Hierarchy Window is a Unity window that simplifies and speeds up the management of scenes that are loaded/unloaded/active in the hierarchy
// Created using Unity 2023.2, but if I'm not mistaken, this should work in older versions of Unity too
using System.Linq;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Whitakr.Utils.Editor
{
public class SceneHierarchyWindow : EditorWindow
{
const float LABEL_PADDING = 10f;
const float BUTTON_WIDTH = 80f;
[MenuItem("Whitakr/Utils/Scene Hierarchy Window")]
public static void ShowWindow()
{
SceneHierarchyWindow window = GetWindow<SceneHierarchyWindow>();
window.titleContent = new("Scene Hierarchy Window");
window.Show();
}
void OnGUI()
{
if (Application.isPlaying)
{
EditorGUILayout.HelpBox("Scene Hierarchy Window is not available in Play Mode.", MessageType.Info);
return;
}
SceneSetup[] setups = EditorSceneManager.GetSceneManagerSetup();
float previousLabelWidth = EditorGUIUtility.labelWidth;
float minLabelWidth = setups
.Select(setup => System.IO.Path.GetFileNameWithoutExtension(setup.path))
.Select(sceneName => GUI.skin.label.CalcSize(new(sceneName)).x)
.Max();
EditorGUIUtility.labelWidth = minLabelWidth + LABEL_PADDING;
foreach (SceneSetup setup in setups)
{
string scenePath = setup.path;
string sceneName = System.IO.Path.GetFileNameWithoutExtension(scenePath);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel(sceneName);
if (setup.isActive)
{
EditorGUILayout.LabelField("Active", EditorStyles.boldLabel);
}
else
{
if (setup.isLoaded)
{
if (GUILayout.Button("Unload", GUILayout.Width(BUTTON_WIDTH)))
{
Unload(scenePath);
}
}
else
{
if (GUILayout.Button("Load", GUILayout.Width(BUTTON_WIDTH)))
{
Load(scenePath);
}
}
if (GUILayout.Button("Set Active", GUILayout.Width(BUTTON_WIDTH)))
{
SetActive(scenePath);
}
}
EditorGUILayout.EndHorizontal();
}
if (setups.Any(s => !s.isLoaded))
{
if (GUILayout.Button("Load All"))
{
foreach (SceneSetup setup in setups)
{
if (!setup.isLoaded)
{
Load(setup.path);
}
}
}
}
else if (setups.Length > 1) // Only show unload all if there are multiple scenes loaded, since Active scene can't be unloaded
{
if (GUILayout.Button("Unload All"))
{
foreach (SceneSetup setup in setups)
{
if (setup.isLoaded && !setup.isActive)
{
Unload(setup.path);
}
}
}
}
EditorGUIUtility.labelWidth = previousLabelWidth;
}
static void Load(string scenePath)
{
EditorSceneManager.OpenScene(scenePath, OpenSceneMode.Additive);
}
static void Unload(string scenePath)
{
EditorSceneManager.CloseScene(SceneManager.GetSceneByPath(scenePath), false);
}
static void SetActive(string scenePath)
{
Scene scene = SceneManager.GetSceneByPath(scenePath);
if (!scene.isLoaded)
{
EditorSceneManager.OpenScene(scenePath, OpenSceneMode.Additive);
}
SceneManager.SetActiveScene(scene);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment