Skip to content

feat: improvements to child scene loader #704

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Assets/Scenes/BossRoom.unity
Git LFS file not shown
2 changes: 1 addition & 1 deletion Packages/com.unity.multiplayer.samples.coop/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
### Added
*
### Changed
*
* Cleaning up child scene loader to remove garbage gameObject and adding automatic expand of child scenes (#704)
### Removed
*
### Fixed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#endif
using UnityEngine;
using UnityEngine.SceneManagement;
using Object = UnityEngine.Object;

/// <summary>
/// Allows setting a scene as a root scene and setting its child scenes. To use this, drag this component on any object in a scene to make that scene a root scene. In the background, ChildSceneLoader will automatically manage this.
Expand All @@ -16,12 +17,14 @@ public class EditorChildSceneLoader : MonoBehaviour
[SerializeField]
public List<SceneAsset> ChildScenesToLoadConfig;

const string k_MenuBase = "Boss Room/Child Scene Loader";

void Update()
{
// DO NOT DELETE keep this so we can enable/disable this script... (used in ChildSceneLoader)
}

public void SaveSceneSetup()
void SaveSceneSetup()
{
ChildScenesToLoadConfig ??= new List<SceneAsset>();
ChildScenesToLoadConfig.Clear();
Expand All @@ -44,32 +47,108 @@ public void ResetSceneSetupToConfig()
sceneSetupToLoad[0].isActive = true;
EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();
EditorSceneManager.RestoreSceneManagerSetup(sceneSetupToLoad.ToArray());

for (int i = 0; i < SceneManager.sceneCount; i++)
{
var scene = SceneManager.GetSceneAt(i);

// hacky way to "expand" a scene. If someone found a cleaner way to do this, let me know
var selection = new List<Object>();
selection.AddRange(Selection.objects);
selection.Add(scene.GetRootGameObjects()[0]);
Selection.objects = selection.ToArray();
}
}
#endif
}

#if UNITY_EDITOR
[CustomEditor(typeof(EditorChildSceneLoader))]
public class ChildSceneLoaderInspectorGUI : Editor
{
public override void OnInspectorGUI()
[MenuItem(k_MenuBase + "/Save Scene Setup To Config")]
static void DoSaveSceneSetupMenu()
{
base.OnInspectorGUI();
var activeScene = EditorSceneManager.GetActiveScene();
var wasDirty = activeScene.isDirty;
var foundLoaders = GameObject.FindObjectsOfType<EditorChildSceneLoader>();
EditorChildSceneLoader loader;
if (foundLoaders.Length == 0)
{
// create loader in scene
var supportingGameObject = new GameObject("YOU SHOULD NOT SEE THIS");
supportingGameObject.hideFlags = HideFlags.DontSaveInBuild | HideFlags.HideInHierarchy; // object only findable through scripts
loader = supportingGameObject.AddComponent<EditorChildSceneLoader>();
SceneManager.MoveGameObjectToScene(supportingGameObject, activeScene);
}
else
{
loader = foundLoaders[0];
}

loader.SaveSceneSetup();
EditorSceneManager.MarkSceneDirty(loader.gameObject.scene);
TrySaveScene(wasDirty, activeScene);
PrintConfig();
}

// wasDirty: was the scene dirty before modifying it? if not, will try to save it directly without asking the user
static void TrySaveScene(bool wasDirty, Scene activeScene)
{
if (!wasDirty)
{
EditorSceneManager.SaveScene(activeScene);
}
else
{
EditorSceneManager.SaveModifiedScenesIfUserWantsTo(new[] { activeScene });
}
}

var currentInspectorObject = (EditorChildSceneLoader)target;
static EditorChildSceneLoader TryFindLoader()
{
var foundLoaders = GameObject.FindObjectsOfType<EditorChildSceneLoader>();
if (foundLoaders.Length > 1)
{
throw new Exception("not normal, should only have one loaded child scene loader");
}

if (GUILayout.Button("Save scene setup to config"))
if (foundLoaders.Length == 0)
{
currentInspectorObject.SaveSceneSetup();
throw new Exception("couldn't find any child scene loader, please use Save Scene setup");
}

if (GUILayout.Button("Reset scene setup from config..."))
return foundLoaders[0];
}

[MenuItem(k_MenuBase + "/Remove Config")]
static void RemoveConfig()
{
var foundObj = TryFindLoader().gameObject;
var parentScene = foundObj.scene;
var wasDirty = parentScene.isDirty;
DestroyImmediate(foundObj);
EditorSceneManager.MarkSceneDirty(parentScene);
TrySaveScene(wasDirty, parentScene);
}

[MenuItem(k_MenuBase + "/Load Scene Setup from Config")]
static void DoResetSceneToConfig()
{
TryFindLoader().ResetSceneSetupToConfig();
}

[MenuItem(k_MenuBase + "/Print Current Config")]
static void PrintConfig()
{
var foundLoader = TryFindLoader();
string toPrint = $"To Load ({foundLoader.ChildScenesToLoadConfig.Count}): ";
foreach (var config in foundLoader.ChildScenesToLoadConfig)
{
currentInspectorObject.ResetSceneSetupToConfig();
toPrint += $"{config.name}, ";
}

Debug.Log(toPrint);
}
#endif
}

#if UNITY_EDITOR

[InitializeOnLoad]
public class ChildSceneLoader
{
Expand Down