Skip to content

Instantly share code, notes, and snippets.

@nekomimi-daimao
Last active February 8, 2021 19:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nekomimi-daimao/a3c9c3783fbe56033ba1475181964731 to your computer and use it in GitHub Desktop.
Save nekomimi-daimao/a3c9c3783fbe56033ba1475181964731 to your computer and use it in GitHub Desktop.
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Nekomimi.Daimao.SceneEntry
{
public abstract class EntryBehaviourBase : MonoBehaviour
{
public Scene Scene => gameObject.scene;
public abstract UniTask PreEntry(EntryEntityBase entryEntity);
public abstract void Entry();
public abstract UniTask PreLeave();
public abstract UniTask PreUnload();
}
public abstract class EntryEntityBase
{
public abstract string SceneName { get; }
}
}
using System.Collections.Generic;
using System.Linq;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Nekomimi.Daimao.SceneEntry
{
public static class SceneEntryLoader
{
private const string LoadingSceneName = "LoadingScene";
public static async UniTask EntryScene(
EntryEntityBase nextEntity,
EntryEntityBase[] additive = null)
{
await UniTask.Yield();
var currentScenes = GetAllLoadedScene();
await SceneManager.LoadSceneAsync(LoadingSceneName, LoadSceneMode.Additive);
var loadingScene = SceneManager.GetSceneByName(LoadingSceneName);
SceneManager.SetActiveScene(loadingScene);
var currentEntry = currentScenes
.Select(DetectEntry)
.Where(entry => entry != null)
.ToArray();
foreach (var entry in currentEntry)
{
await entry.PreLeave();
}
var nextSceneEntities = new List<EntryEntityBase>();
if (additive != null)
{
nextSceneEntities.AddRange(additive);
}
nextSceneEntities.Add(nextEntity);
var nextSceneName = nextSceneEntities
.Select(entity => entity.SceneName)
.Distinct()
.ToList();
foreach (var entry in currentEntry)
{
if (nextSceneName.Contains(entry.Scene.name))
{
continue;
}
await entry.PreUnload();
await SceneManager.UnloadSceneAsync(entry.Scene);
}
await UniTask.Yield();
await Resources.UnloadUnusedAssets();
await UniTask.Yield();
var nextEntry = new List<EntryBehaviourBase>();
foreach (var entity in nextSceneEntities)
{
var entry = await LoadSceneAndEntryAsync(entity);
if (entry == null)
{
continue;
}
await entry.PreEntry(entity);
nextEntry.Add(entry);
}
var nextScene = SceneManager.GetSceneByName(nextEntity.SceneName);
SceneManager.SetActiveScene(nextScene);
await SceneManager.UnloadSceneAsync(LoadingSceneName);
await UniTask.Yield();
foreach (var entryBehaviourBase in nextEntry)
{
entryBehaviourBase.Entry();
}
}
public static Scene[] GetAllLoadedScene()
{
return Enumerable.Range(0, SceneManager.sceneCount)
.Select(SceneManager.GetSceneAt)
.ToArray();
}
private static async UniTask<EntryBehaviourBase> LoadSceneAndEntryAsync(EntryEntityBase entity)
{
if (!SceneManager.GetSceneByName(entity.SceneName).isLoaded)
{
await SceneManager.LoadSceneAsync(entity.SceneName, LoadSceneMode.Additive);
}
await UniTask.Yield();
var scene = SceneManager.GetSceneByName(entity.SceneName);
return DetectEntry(scene);
}
private static EntryBehaviourBase DetectEntry(Scene scene)
{
if (!scene.isLoaded)
{
return null;
}
return scene.GetRootGameObjects()
.Select(rootGameObject => rootGameObject.GetComponent<EntryBehaviourBase>())
.FirstOrDefault(entry => entry != null);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment