Skip to content

Commit

Permalink
Improve library UX, quality of life changes (guards, more config)
Browse files Browse the repository at this point in the history
  • Loading branch information
Edvinas01 committed Oct 15, 2022
1 parent 58d8e25 commit 25ecdd8
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 49 deletions.
13 changes: 13 additions & 0 deletions Assets/Scenes/SetupScene.unity
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
initialCollection: {fileID: 11400000, guid: 29b938dba078c954bb3082acd12f028d, type: 2}
initialSceneLoadMode: 1
collectionEvents:
onLoadEntered:
m_PersistentCalls:
Expand All @@ -580,6 +581,18 @@ MonoBehaviour:
onUnloadExited:
m_PersistentCalls:
m_Calls: []
onShowTransitionEntered:
m_PersistentCalls:
m_Calls: []
onShowTransitionExited:
m_PersistentCalls:
m_Calls: []
onHideTransitionEntered:
m_PersistentCalls:
m_Calls: []
onHideTransitionExited:
m_PersistentCalls:
m_Calls: []
sceneEvents:
onLoadEntered:
m_PersistentCalls:
Expand Down
14 changes: 13 additions & 1 deletion Packages/com.chark.scriptable-scenes/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.0.4] - 2022-09-28

### Added
- Added more initial scene load options to `ScriptableSceneController`.
- Added more guards when loading invalid scenes.
-
### Changed
- Updated package.json with new version.

### Fixed
- `ScriptableSceneController` not cleaning up `IsLoading` and `loadingCollection` on exception.

## [0.0.3] - 2022-09-28

### Fixed
Expand All @@ -25,7 +37,7 @@ Minor UX updates and bug fixes.
### Fixed
- Incorrect collection progress being reported when a collection is loading.

## [0.0.1] - 2022-05-21
## [v0.0.1] - 2022-05-21
Initial preview version.

### Added
Expand Down
45 changes: 44 additions & 1 deletion Packages/com.chark.scriptable-scenes/Runtime/ScriptableScene.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,17 @@ public override void SetActive()

private IEnumerator LoadInternalRoutine()
{
if (sceneBuildIndex < 0)
{
Debug.LogWarning(
"Cannot load an invalid Scene Build Index. Make sure a Scene Asset is assigned, " +
"ensure that the scene is added to project Build Settings and is enabled",
this
);

yield break;
}

var operation = SceneManager.LoadSceneAsync(sceneBuildIndex, LoadSceneMode.Additive);

while (operation.isDone == false)
Expand All @@ -142,12 +153,34 @@ private IEnumerator LoadInternalRoutine()

private IEnumerator UnloadInternalRoutine()
{
if (sceneBuildIndex < 0)
{
Debug.LogWarning(
"Cannot unload invalid Scene Build Index. Make sure a Scene Asset is assigned, " +
"ensure that the scene is added to project Build Settings and is enabled",
this
);

yield break;
}

yield return SceneManager.UnloadSceneAsync(sceneBuildIndex);
}

private void SetActiveInternal()
{
var scene = GetScene();
if (scene.IsValid() == false)
{
Debug.LogWarning(
"Cannot activate an invalid scene. Make sure a Scene Asset is assigned, " +
"ensure that the scene is added to project Build Settings and is enabled",
this
);

return;
}

SceneManager.SetActiveScene(scene);
}

Expand All @@ -159,7 +192,17 @@ private bool IsLoaded()

private Scene GetScene()
{
return SceneManager.GetSceneByBuildIndex(sceneBuildIndex);
if (sceneBuildIndex >= 0)
{
return SceneManager.GetSceneByBuildIndex(sceneBuildIndex);
}

var invalidScene = new Scene
{
name = "Invalid Scene"
};

return invalidScene;
}

#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,28 @@ public sealed class ScriptableSceneController : MonoBehaviour
{
#region Editor Fields

private enum SceneLoadMode
{
[Tooltip("Scenes will not be loaded automatically")]
None,

[Tooltip("Automatically load scenes in Awake")]
Awake,

[Tooltip("Automatically load scenes in Start")]
Start
}

// ReSharper disable once NotAccessedField.Local
[Header("Configuration")]
[Tooltip("Scene collection which is first to be loaded when the game runs in build mode")]
[SerializeField]
private BaseScriptableSceneCollection initialCollection;

[Tooltip("Should and when " + nameof(initialCollection) + " be loaded?")]
[SerializeField]
private SceneLoadMode initialSceneLoadMode = SceneLoadMode.Start;

[Header("Events")]
[Tooltip("handler for global (invoked for all collections) collection events")]
[SerializeField]
Expand Down Expand Up @@ -63,40 +79,31 @@ public sealed class ScriptableSceneController : MonoBehaviour

#region Unity Lifecycle

private IEnumerator Start()
private void Awake()
{
#if UNITY_EDITOR
if (ScriptableSceneUtilities.TryGetSelectedCollection(out var selected))
{
yield return LoadSceneCollectionRoutine(selected);
yield break;
}

if (ScriptableSceneUtilities.TryGetLoadedCollection(out var loaded))
if (initialSceneLoadMode != SceneLoadMode.Awake)
{
yield return LoadSceneCollectionRoutine(loaded);
yield break;
return;
}

Debug.LogWarning(
$"Cannot load initial {nameof(BaseScriptableSceneCollection)}, make sure a valid " +
$"{nameof(BaseScriptableSceneCollection)} exists which matches currently loaded " +
$"scenes or use the Scene Manager Window",
this
);

#if UNITY_EDITOR
LoadScriptableSceneCollection();
#else
if (initialCollection == false)
LoadInitialSceneCollection();
#endif
}

private void Start()
{
if (initialSceneLoadMode != SceneLoadMode.Start)
{
Debug.LogWarning(
$"{nameof(initialCollection)} is not set, initial scene setup will not be " +
$"loaded",
this
);
yield break;
return;
}

yield return LoadSceneCollectionRoutine(initialCollection);
#if UNITY_EDITOR
LoadScriptableSceneCollection();
#else
LoadInitialSceneCollection();
#endif
}

Expand Down Expand Up @@ -155,6 +162,61 @@ public bool TryGetLoadedSceneCollection(out BaseScriptableSceneCollection collec

#region Private Methods

/// <summary>
/// Load scene collection based on custom Scriptable Scene logic.
/// </summary>
private void LoadScriptableSceneCollection()
{
StartCoroutine(LoadScriptableSceneCollectionRoutine());
}

/// <summary>
/// Load scene collection specified in <see cref="initialCollection"/>.
/// </summary>
// ReSharper disable once UnusedMember.Local
private void LoadInitialSceneCollection()
{
StartCoroutine(LoadInitialSceneCollectionRoutine());
}

private IEnumerator LoadScriptableSceneCollectionRoutine()
{
if (ScriptableSceneUtilities.TryGetSelectedCollection(out var selected))
{
yield return LoadSceneCollectionRoutine(selected);
yield break;
}

if (ScriptableSceneUtilities.TryGetLoadedCollection(out var loaded))
{
yield return LoadSceneCollectionRoutine(loaded);
yield break;
}

Debug.LogWarning(
$"Cannot load initial {nameof(BaseScriptableSceneCollection)}, make sure a valid " +
$"{nameof(BaseScriptableSceneCollection)} exists which matches currently loaded " +
$"scenes or use the Scene Manager Window",
this
);
}

private IEnumerator LoadInitialSceneCollectionRoutine()
{
if (initialCollection == false)
{
Debug.LogWarning(
$"{nameof(initialCollection)} is not set, initial scene setup will not be " +
$"loaded",
this
);

yield break;
}

yield return LoadSceneCollectionRoutine(initialCollection);
}

private IEnumerator LoadSceneCollectionRoutine(BaseScriptableSceneCollection collection)
{
if (collection.SceneCount == 0)
Expand Down Expand Up @@ -182,11 +244,16 @@ private IEnumerator LoadSceneCollectionRoutine(BaseScriptableSceneCollection col
loadingCollection = collection;
IsLoading = true;

yield return LoadSceneCollectionInternalRoutine(collection);

loadingCollection = null;
loadedCollection = collection;
IsLoading = false;
try
{
yield return LoadSceneCollectionInternalRoutine(collection);
loadedCollection = collection;
}
finally
{
loadingCollection = null;
IsLoading = false;
}
}

private IEnumerator LoadSceneCollectionInternalRoutine(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ internal static bool TryGetLoadedScene(BaseScriptableScene scriptableScene, out
var targetSceneBuildIndex = scriptableScene.SceneBuildIndex;
scene = default;

foreach (var loadedScene in GetLoadedScenes())
foreach (var loadedScene in GetValidScenes())
{
var loadedSceneBuildIndex = loadedScene.buildIndex;
if (targetSceneBuildIndex == loadedSceneBuildIndex)
Expand Down Expand Up @@ -253,31 +253,31 @@ SceneEventHandler otherHandler

#region Private Methods

private static IEnumerable<Scene> GetLoadedScenes()
{
for (var sceneIndex = 0; sceneIndex < SceneManager.sceneCount; sceneIndex++)
{
var scene = SceneManager.GetSceneAt(sceneIndex);
if (scene.isLoaded)
{
yield return scene;
}
}
}

private static bool IsLoaded(BaseScriptableSceneCollection collection)
{
var scriptableSceneIndices = collection.Scenes
.Select(scene => scene.SceneBuildIndex);

var uniqueScriptableSceneIndices = new HashSet<int>(scriptableSceneIndices);

var loadedSceneIndices = GetLoadedScenes().Select(scene => scene.buildIndex);
var uniqueLoadedSceneIndices = new HashSet<int>(loadedSceneIndices);
var validSceneIndices = GetValidScenes().Select(scene => scene.buildIndex);
var uniqueLoadedSceneIndices = new HashSet<int>(validSceneIndices);

return uniqueScriptableSceneIndices.SetEquals(uniqueLoadedSceneIndices);
}

private static IEnumerable<Scene> GetValidScenes()
{
for (var sceneIndex = 0; sceneIndex < SceneManager.sceneCount; sceneIndex++)
{
var scene = SceneManager.GetSceneAt(sceneIndex);
if (scene.IsValid())
{
yield return scene;
}
}
}

#endregion
}
}
2 changes: 1 addition & 1 deletion Packages/com.chark.scriptable-scenes/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"name": "CHARK",
"url": "https://chark.io"
},
"version": "0.0.3",
"version": "0.0.4",
"unity": "2020.3",
"description": "Simple scene loading and management system for Unity Engine, implemented via scriptable objects.",
"keywords": [
Expand Down

0 comments on commit 25ecdd8

Please sign in to comment.