Skip to content

Instantly share code, notes, and snippets.

@thebeardphantom
Last active August 29, 2015 14:19
Show Gist options
  • Save thebeardphantom/08b909102703d8168594 to your computer and use it in GitHub Desktop.
Save thebeardphantom/08b909102703d8168594 to your computer and use it in GitHub Desktop.
SceneLoader
using System.Collections;
using System.Linq;
using UnityEngine;
namespace Rubycone.Utils {
public delegate void LoadComplete(GameObject loaded);
public class SceneLoader : MonoBehaviour {
public event LoadComplete LoadComplete;
public AsyncOperation operation { get; private set; }
public Coroutine loadRoutine { get; private set; }
public SceneVar scene { get; private set; }
Transform temp;
bool running;
public static SceneLoader Create(SceneVar scene) {
var loader = new GameObject("SCENELOADER_" + System.Guid.NewGuid().ToString()).AddComponent<SceneLoader>();
GameObject.DontDestroyOnLoad(loader.gameObject);
loader.scene = scene;
return loader;
}
public static SceneLoader[] Create(params SceneVar[] scenes) {
var loaders = new SceneLoader[scenes.Length];
for(int i = 0; i < scenes.Length; i++) {
loaders[i] = Create(scenes[i]);
}
return loaders;
}
public void Load() {
if(running) {
return;
}
running = true;
loadRoutine = StartCoroutine(_Load());
}
public void LoadAsync() {
if(running) {
return;
}
running = true;
loadRoutine = StartCoroutine(_LoadAsync());
}
public void LoadAdditive() {
if(running) {
return;
}
running = true;
loadRoutine = StartCoroutine(_LoadAdditive());
}
public void LoadAdditiveAsync() {
if(running) {
return;
}
running = true;
loadRoutine = StartCoroutine(_LoadAdditiveAsync());
}
IEnumerator _Load() {
Application.LoadLevel(scene.index);
yield return null;
var newSceneRoot = ParentNewSceneTransforms();
if(LoadComplete != null) {
LoadComplete(newSceneRoot);
}
running = false;
Destroy(gameObject);
}
IEnumerator _LoadAsync() {
operation = Application.LoadLevelAsync(scene.index);
yield return operation;
var newSceneRoot = ParentNewSceneTransforms();
if(LoadComplete != null) {
LoadComplete(newSceneRoot);
}
running = false;
Destroy(gameObject);
}
IEnumerator _LoadAdditive() {
StoreCurrent();
Application.LoadLevelAdditive(scene.index);
yield return null;
var newSceneRoot = ParentNewSceneTransforms();
UnloadTemp();
if(LoadComplete != null) {
LoadComplete(newSceneRoot);
}
running = false;
Destroy(gameObject);
}
IEnumerator _LoadAdditiveAsync() {
StoreCurrent();
operation = Application.LoadLevelAdditiveAsync(scene.index);
yield return operation;
var newSceneRoot = ParentNewSceneTransforms();
UnloadTemp();
if(LoadComplete != null) {
LoadComplete(newSceneRoot);
}
running = false;
Destroy(gameObject);
}
/// <summary>
/// Unloads temp storage.
/// </summary>
/// <param name="temp"></param>
void UnloadTemp() {
for(int i = 0; i < temp.childCount; i++) {
temp.GetChild(i).parent = null;
}
Destroy(temp.gameObject);
}
/// <summary>
/// Stores all root-level transforms from the newly loaded scene to a transform.
/// </summary>
/// <returns>The new temp parent transform</returns>
GameObject ParentNewSceneTransforms() {
var roots = FindObjectsOfType<Transform>().Where(t => t.parent == null);
var newRoot = new GameObject(scene.name);
foreach(var r in roots) {
r.parent = newRoot.transform;
}
return newRoot;
}
/// <summary>
/// Stores all current root-level transforms to a temp transform
/// </summary>
/// <returns>The new temp parent transform</returns>
void StoreCurrent() {
var roots = FindObjectsOfType<Transform>().Where(t => t.parent == null);
temp = new GameObject("SL_TEMP_STORAGE_" + System.Guid.NewGuid().ToString()).transform;
foreach(var r in roots) {
r.parent = temp;
}
}
}
}
namespace Rubycone.Utils {
[System.Serializable]
public class SceneVar {
public string path = string.Empty;
public string name = string.Empty;
public int index;
public SceneVar() { }
public SceneVar(string name) {
this.name = name;
}
public SceneVar(int index) {
this.index = index;
}
}
}
using UnityEditor;
using UnityEngine;
namespace Rubycone.Utils {
[CustomPropertyDrawer(typeof(SceneVar))]
public class SceneVarEditor : PropertyDrawer {
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
var levelNames = new string[EditorBuildSettings.scenes.Length];
for(int i=0; i < EditorBuildSettings.scenes.Length; i++) {
if(!EditorBuildSettings.scenes[i].enabled) {
continue;
}
var scenePath = EditorBuildSettings.scenes[i].path;
var seperators = new string[2] { "/", "." };
var splitPath = scenePath.Split(seperators, System.StringSplitOptions.None);
levelNames[i] = splitPath[splitPath.Length - 2];
}
EditorGUI.BeginProperty(position, label, property);
var levelIndexProp = property.FindPropertyRelative("index");
var levelPath = property.FindPropertyRelative("path");
var levelName = property.FindPropertyRelative("name");
int selectedLevelIndex = levelIndexProp.intValue;
selectedLevelIndex = EditorGUI.Popup(position, label.text, selectedLevelIndex, levelNames);
levelIndexProp.intValue = selectedLevelIndex;
levelPath.stringValue = EditorBuildSettings.scenes[selectedLevelIndex].path;
levelName.stringValue = levelNames[selectedLevelIndex];
EditorGUI.EndProperty();
}
}
}
@thebeardphantom
Copy link
Author

Place SceneVarEditor in an Editor folder, other scripts can go anywhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment