Skip to content
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

Sceneloader progression #30

Merged
merged 2 commits into from
Feb 22, 2024
Merged
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
31 changes: 0 additions & 31 deletions Runtime/Assets/Compatibility/CompatibleSceneLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,10 @@
using Cysharp.Threading.Tasks;
#endif

#if UNITY_EDITOR
using UnityEditor.SceneManagement;
#endif

namespace Mew.Core.Assets
{
internal static class CompatibleSceneLoader
{
internal static async ValueTask<SceneHandle> LoadSceneAsync(UnifiedScene unifiedScene, LoadSceneParameters parameters)
{
#if UNITY_2023_2_OR_NEWER || USE_UNITASK
await SceneManager.LoadSceneAsync(unifiedScene.SceneReference, parameters);
#else
var asyncOp = SceneManager.LoadSceneAsync(unifiedScene.SceneReference, parameters);
while (!asyncOp.isDone) await TaskHelper.NextFrame();
#endif
var loadedScene = SceneManager.GetSceneAt(SceneManager.loadedSceneCount - 1);
return new SceneHandle(loadedScene);
}

internal static async ValueTask UnloadSceneAsync(SceneHandle sceneHandle)
{
#if UNITY_2023_2_OR_NEWER || USE_UNITASK
Expand All @@ -36,20 +20,5 @@ internal static async ValueTask UnloadSceneAsync(SceneHandle sceneHandle)
while (!asyncOp.isDone) await TaskHelper.NextFrame();
#endif
}

#if UNITY_EDITOR
public static async Task<ISceneHandle> LoadEditorSceneAsync(UnifiedScene unifiedScene, LoadSceneParameters parameters)
{

#if UNITY_2023_2_OR_NEWER || USE_UNITASK
await EditorSceneManager.LoadSceneAsyncInPlayMode(unifiedScene.EditorScenePath , parameters ) ;
#else
var asyncOp = EditorSceneManager.LoadSceneAsyncInPlayMode(unifiedScene.EditorScenePath , parameters ) ;
while (!asyncOp.isDone) await TaskHelper.NextFrame();
#endif
var loadedScene = SceneManager.GetSceneAt(SceneManager.loadedSceneCount - 1);
return new SceneHandle(loadedScene);
}
#endif
}
}
5 changes: 4 additions & 1 deletion Runtime/Assets/Scene/ISceneHandle.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine.SceneManagement;

namespace Mew.Core.Assets
{
public interface ISceneHandle : IEquatable<Scene>
{
ValueTask<Scene> GetScene();
ValueTask<Scene> GetScene(CancellationToken ct);
public float Progress { get; }
bool Completed { get; }
}
}
43 changes: 39 additions & 4 deletions Runtime/Assets/Scene/SceneHandle.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,55 @@
using System.Threading.Tasks;
using System.Threading;
using System.Threading.Tasks;
using Mew.Core.TaskHelpers;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace Mew.Core.Assets
{
public class SceneHandle : ISceneHandle
{
public Scene Scene { get; }
public AsyncOperation AsyncOp { get; }
public Scene Scene { get; private set; }
public float Progress => AsyncOp.progress;
public bool Completed => AsyncOp.isDone;

public SceneHandle(AsyncOperation asyncOp)
{
AsyncOp = asyncOp;
AsyncOp.completed += OnCompleted;
}

public SceneHandle(Scene scene)
{
Scene = scene;
}

public async ValueTask<Scene> GetScene()
private void OnCompleted(AsyncOperation operation)
{
AsyncOp.completed -= OnCompleted;
Scene = SceneManager.GetSceneAt(SceneManager.sceneCount - 1);
}

public async ValueTask<Scene> GetScene(CancellationToken ct)
{
return await Task.FromResult(Scene);
if (!AsyncOp.isDone)
{
#if UNITY_2023_2_OR_NEWER
await AsyncOp;
#else
while (!AsyncOp.isDone) await TaskHelper.NextFrame(ct);
#endif
}

// not pass cancellation token to SceneManager.UnloadSceneAsync
if (!Scene.IsValid()) await TaskHelper.NextFrame();

if (ct.IsCancellationRequested)
{
SceneManager.UnloadSceneAsync(Scene);
ct.ThrowIfCancellationRequested();
}
return Scene;
}

public bool Equals(Scene other)
Expand Down
13 changes: 11 additions & 2 deletions Runtime/Assets/Scene/SceneInstanceHandle.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#if USE_MEW_CORE_ASSETS
using System.Threading;
using System.Threading.Tasks;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.Exceptions;
Expand All @@ -10,17 +11,25 @@ namespace Mew.Core.Assets
public class SceneInstanceHandle : ISceneHandle
{
public AsyncOperationHandle<SceneInstance> Handle { get; }
private bool Comeleted => Handle.IsDone;
public float Progress => Handle.PercentComplete;
public bool Completed => Handle.IsDone;

public SceneInstanceHandle(AsyncOperationHandle<SceneInstance> asyncOperationHandle)
{
Handle = asyncOperationHandle;
}

public async ValueTask<Scene> GetScene()
public async ValueTask<Scene> GetScene(CancellationToken ct)
{
if (!Handle.IsDone)
await Handle.Task;

if (ct.IsCancellationRequested)
{
await UnifiedSceneLoader.UnloadAsync(this);
ct.ThrowIfCancellationRequested();
}

return Handle.Result.Scene;
}

Expand Down
13 changes: 11 additions & 2 deletions Runtime/Assets/Scene/SceneLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,27 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Mew.Core.TaskHelpers;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace Mew.Core.Assets
{
public class SceneLoader : IAsyncDisposable
{
private List<ISceneHandle> SceneHandles { get; } = new();
private List<ISceneHandle> LoadingHandles { get; } = new();
private bool Disposed { get; set; }
public float Progression
=> LoadingHandles.Any()
? LoadingHandles.Sum(x => x.Progress) / LoadingHandles.Count
: 1f;

public async ValueTask<Scene> LoadAsync(UnifiedScene unifiedScene, CancellationToken cancellationToken = default)
{
var handle = await UnifiedSceneLoader.LoadAsync(unifiedScene, cancellationToken);
var scene = await handle.GetScene();
var handle = UnifiedSceneLoader.LoadAsync(unifiedScene);
LoadingHandles.Add(handle);
var scene = await handle.GetScene(cancellationToken);

if (Disposed)
{
Expand All @@ -27,6 +35,7 @@ public async ValueTask<Scene> LoadAsync(UnifiedScene unifiedScene, CancellationT
throw new TaskCanceledException();
}

LoadingHandles.Remove(handle);
SceneHandles.Add(handle);
return scene;
}
Expand Down
8 changes: 5 additions & 3 deletions Runtime/Assets/Scene/UnifiedSceneLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace Mew.Core.Assets
{
public static class UnifiedSceneLoader
{
public static async Task<ISceneHandle> LoadAsync(UnifiedScene unifiedScene, CancellationToken cancellationToken)
public static ISceneHandle LoadAsync(UnifiedScene unifiedScene)
{
var parameters = new LoadSceneParameters(LoadSceneMode.Additive, LocalPhysicsMode.None);
ISceneHandle handle;
Expand All @@ -42,13 +42,15 @@ public static async Task<ISceneHandle> LoadAsync(UnifiedScene unifiedScene, Canc
#endif
if (unifiedScene.SceneReference is not null && unifiedScene.SceneReference.IsValid)
{
handle = await CompatibleSceneLoader.LoadSceneAsync(unifiedScene, parameters);
var asyncOp = SceneManager.LoadSceneAsync(unifiedScene.SceneReference, parameters);
handle = new SceneHandle(asyncOp);
}
#if UNITY_EDITOR
// for test use
else if (!string.IsNullOrEmpty(unifiedScene.EditorScenePath))
{
handle = await CompatibleSceneLoader.LoadEditorSceneAsync(unifiedScene, parameters);
var asyncOp = EditorSceneManager.LoadSceneAsyncInPlayMode(unifiedScene.EditorScenePath , parameters ) ;
handle = new SceneHandle(asyncOp);
}
#endif
else
Expand Down