diff --git a/Scripts/AddressableAssets/AddressableAssetDownloadManager.cs b/Scripts/AddressableAssets/AddressableAssetDownloadManager.cs index a2df18a..7d2cd19 100644 --- a/Scripts/AddressableAssets/AddressableAssetDownloadManager.cs +++ b/Scripts/AddressableAssets/AddressableAssetDownloadManager.cs @@ -1,3 +1,4 @@ +using Cysharp.Threading.Tasks; using System.Threading.Tasks; using UnityEngine; using UnityEngine.AddressableAssets; @@ -27,6 +28,7 @@ public partial class AddressableAssetDownloadManager : MonoBehaviour private async void Start() { + await UniTask.Yield(); onStart?.Invoke(); AsyncOperationHandle settingsAsyncOp = settingsAssetReference.LoadAssetAsync(); await settingsAsyncOp.Task; @@ -82,15 +84,16 @@ await Download( } LoadedCount++; } + await UniTask.Yield(); onDownloadedAll?.Invoke(); // Instantiates for (int i = 0; i < settings.InitialObjects.Count; ++i) { try { - AsyncOperationHandle getSizeOp = Addressables.InstantiateAsync(settings.InitialObjects[i].RuntimeKey); - await getSizeOp.Task; - Logging.Log($"Initialized {getSizeOp.Result.name}"); + AsyncOperationHandle instantiateOp = Addressables.InstantiateAsync(settings.InitialObjects[i].RuntimeKey); + await instantiateOp.Task; + Logging.Log($"Initialized {instantiateOp.Result.name}"); } catch (System.Exception ex) { @@ -158,12 +161,12 @@ public static async Task DownloadAndLoadScene( System.Action onDepsDownloaded) { await Download(runtimeKey, onFileSizeRetrieving, onFileSizeRetrieved, onDepsDownloading, onDepsFileDownloading, onDepsDownloaded); - AsyncOperationHandle getSizeOp = Addressables.LoadSceneAsync(runtimeKey, loadSceneParameters); - while (!getSizeOp.IsDone) + AsyncOperationHandle loadSceneOp = Addressables.LoadSceneAsync(runtimeKey, loadSceneParameters); + while (!loadSceneOp.IsDone) { - await Task.Yield(); + await UniTask.Yield(); } - return getSizeOp.Result; + return loadSceneOp.Result; } public static async Task DownloadAndInstantiate( @@ -175,12 +178,12 @@ public static async Task DownloadAndInstantiate( System.Action onDepsDownloaded) { await Download(runtimeKey, onFileSizeRetrieving, onFileSizeRetrieved, onDepsDownloading, onDepsFileDownloading, onDepsDownloaded); - AsyncOperationHandle getSizeOp = Addressables.InstantiateAsync(runtimeKey); - while (!getSizeOp.IsDone) + AsyncOperationHandle instantiateOp = Addressables.InstantiateAsync(runtimeKey); + while (!instantiateOp.IsDone) { - await Task.Yield(); + await UniTask.Yield(); } - return getSizeOp.Result; + return instantiateOp.Result; } public static async Task Download( @@ -193,23 +196,28 @@ public static async Task Download( { // Get download size AsyncOperationHandle getSizeOp = Addressables.GetDownloadSizeAsync(runtimeKey); + await UniTask.Yield(); onFileSizeRetrieving?.Invoke(); while (!getSizeOp.IsDone) { - await Task.Yield(); + await UniTask.Yield(); } long fileSize = getSizeOp.Result; + await UniTask.Yield(); onFileSizeRetrieved.Invoke(fileSize); // Download dependencies if (fileSize > 0) { AsyncOperationHandle downloadOp = Addressables.DownloadDependenciesAsync(runtimeKey); + await UniTask.Yield(); onDepsDownloading?.Invoke(); while (!downloadOp.IsDone) { - onDepsFileDownloading?.Invoke((long)(downloadOp.PercentComplete * fileSize), fileSize, downloadOp.PercentComplete); - await Task.Yield(); + await UniTask.Yield(); + float percentageComplete = downloadOp.GetDownloadStatus().Percent; + onDepsFileDownloading?.Invoke((long)(percentageComplete * fileSize), fileSize, percentageComplete); } + await UniTask.Yield(); onDepsDownloaded?.Invoke(); Addressables.ReleaseInstance(downloadOp); } diff --git a/Scripts/AddressableAssets/AddressableAssetsManager.cs b/Scripts/AddressableAssets/AddressableAssetsManager.cs index 2dab646..d0d7c9a 100644 --- a/Scripts/AddressableAssets/AddressableAssetsManager.cs +++ b/Scripts/AddressableAssets/AddressableAssetsManager.cs @@ -11,8 +11,7 @@ public static class AddressableAssetsManager private static Dictionary s_loadedAssets = new Dictionary(); private static Dictionary s_assetRefs = new Dictionary(); - public static async Task GetOrLoadAssetAsync(this TAssetRef assetRef, System.Action handlerCallback = null) - where TAssetRef : AssetReference + public static async Task GetOrLoadAssetAsync(this AssetReference assetRef, System.Action handlerCallback = null) where TType : Component { if (s_loadedAssets.TryGetValue(assetRef.RuntimeKey, out GameObject result)) @@ -25,8 +24,7 @@ public static async Task GetOrLoadAssetAsync(this TAsse return handlerResult.GetComponent(); } - public static TType GetOrLoadAsset(this TAssetRef assetRef, System.Action handlerCallback = null) - where TAssetRef : AssetReference + public static TType GetOrLoadAsset(this AssetReference assetRef, System.Action handlerCallback = null) where TType : Component { if (s_loadedAssets.TryGetValue(assetRef.RuntimeKey, out GameObject result)) @@ -39,6 +37,30 @@ public static TType GetOrLoadAsset(this TAssetRef assetRef, Sy return handlerResult.GetComponent(); } + public static async Task GetOrLoadAssetAsync(this AssetReference assetRef, System.Action handlerCallback = null) + { + if (s_loadedAssets.TryGetValue(assetRef.RuntimeKey, out GameObject result)) + return result; + AsyncOperationHandle handler = Addressables.LoadAssetAsync(assetRef.RuntimeKey); + handlerCallback?.Invoke(handler); + GameObject handlerResult = await handler.Task; + s_loadedAssets[assetRef.RuntimeKey] = handlerResult; + s_assetRefs[assetRef.RuntimeKey] = handler; + return handlerResult; + } + + public static GameObject GetOrLoadAsset(this AssetReference assetRef, System.Action handlerCallback = null) + { + if (s_loadedAssets.TryGetValue(assetRef.RuntimeKey, out GameObject result)) + return result; + AsyncOperationHandle handler = Addressables.LoadAssetAsync(assetRef.RuntimeKey); + handlerCallback?.Invoke(handler); + GameObject handlerResult = handler.WaitForCompletion(); + s_loadedAssets[assetRef.RuntimeKey] = handlerResult; + s_assetRefs[assetRef.RuntimeKey] = handler; + return handlerResult; + } + public static void Release(this TAssetRef assetRef) where TAssetRef : AssetReference { diff --git a/Scripts/GameApi/LiteNetLibAdditiveSceneLoader.cs b/Scripts/GameApi/LiteNetLibAdditiveSceneLoader.cs index edf9b7d..b1c5a20 100644 --- a/Scripts/GameApi/LiteNetLibAdditiveSceneLoader.cs +++ b/Scripts/GameApi/LiteNetLibAdditiveSceneLoader.cs @@ -60,15 +60,19 @@ public async UniTask LoadAll(LiteNetLibGameManager manager, string sceneNam { string loadingName = $"{sceneName}_{loadCount++}"; // Load the scene + await UniTask.Yield(); manager.Assets.onLoadSceneStart.Invoke(loadingName, true, isOnline, 0f); var op = SceneManager.LoadSceneAsync( scenes[i].SceneName, new LoadSceneParameters(LoadSceneMode.Additive)); - while (!op.isDone) + op.allowSceneActivation = false; + while (op.progress < 0.9f) { - await UniTask.NextFrame(); + await UniTask.Yield(); manager.Assets.onLoadSceneProgress.Invoke(loadingName, true, isOnline, op.progress); } + op.allowSceneActivation = true; + await UniTask.Yield(); manager.Assets.onLoadSceneFinish.Invoke(loadingName, true, isOnline, 1f); manager.LoadedAdditiveScenesCount++; manager.Assets.onLoadAdditiveSceneProgress.Invoke(manager.LoadedAdditiveScenesCount, manager.TotalAdditiveScensCount); @@ -78,6 +82,7 @@ public async UniTask LoadAll(LiteNetLibGameManager manager, string sceneNam { string loadingName = $"{sceneName}_{loadCount++}"; // Download the scene + await UniTask.Yield(); await AddressableAssetDownloadManager.Download( addressableScenes[i].RuntimeKey, manager.Assets.onSceneFileSizeRetrieving.Invoke, @@ -92,9 +97,11 @@ await AddressableAssetDownloadManager.Download( new LoadSceneParameters(LoadSceneMode.Additive)); while (!op.IsDone) { - await UniTask.NextFrame(); - manager.Assets.onLoadSceneProgress.Invoke(loadingName, true, isOnline, op.PercentComplete); + await UniTask.Yield(); + float percentageComplete = op.GetDownloadStatus().Percent; + manager.Assets.onLoadSceneProgress.Invoke(loadingName, true, isOnline, percentageComplete); } + await UniTask.Yield(); manager.Assets.onLoadSceneFinish.Invoke(loadingName, true, isOnline, 1f); manager.LoadedAdditiveScenesCount++; manager.Assets.onLoadAdditiveSceneProgress.Invoke(manager.LoadedAdditiveScenesCount, manager.TotalAdditiveScensCount); diff --git a/Scripts/GameApi/LiteNetLibAssets.cs b/Scripts/GameApi/LiteNetLibAssets.cs index 66d144a..1245cd4 100644 --- a/Scripts/GameApi/LiteNetLibAssets.cs +++ b/Scripts/GameApi/LiteNetLibAssets.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using UnityEngine; using UnityEngine.Events; +using UnityEngine.SceneManagement; namespace LiteNetLibManager { @@ -162,7 +163,7 @@ public async Task RegisterAddressablePrefabAsync(AssetRefere return null; } if (Manager.LogDev) Logging.Log(LogTag, $"RegisterAddressablePrefab [{addressablePrefab.HashAssetId}]"); - LiteNetLibIdentity prefab = await addressablePrefab.GetOrLoadAssetAsync(); + LiteNetLibIdentity prefab = await addressablePrefab.GetOrLoadAssetAsync(); GuidToPrefabs[addressablePrefab.HashAssetId] = prefab; return prefab; } @@ -175,7 +176,7 @@ public LiteNetLibIdentity RegisterAddressablePrefab(AssetReferenceLiteNetLibIden return null; } if (Manager.LogDev) Logging.Log(LogTag, $"RegisterAddressablePrefab [{addressablePrefab.HashAssetId}]"); - LiteNetLibIdentity prefab = addressablePrefab.GetOrLoadAsset(); + LiteNetLibIdentity prefab = addressablePrefab.GetOrLoadAsset(); GuidToPrefabs[addressablePrefab.HashAssetId] = prefab; return prefab; } @@ -334,15 +335,25 @@ public void PushInstanceBack(LiteNetLibIdentity instance) public void RegisterSceneObjects() { SceneObjects.Clear(); - LiteNetLibIdentity[] sceneObjects = FindObjectsOfType(); - for (int i = 0; i < sceneObjects.Length; ++i) + for (int i = 0; i < SceneManager.sceneCount; ++i) { - LiteNetLibIdentity sceneObject = sceneObjects[i]; - if (sceneObject.ObjectId > 0) + Scene scene = SceneManager.GetSceneAt(i); + if (!scene.isLoaded) + continue; + GameObject[] rootObjects = scene.GetRootGameObjects(); + for (int j = 0; j < rootObjects.Length; ++j) { - sceneObject.gameObject.SetActive(false); - SceneObjects[sceneObject.ObjectId] = sceneObject; - LiteNetLibIdentity.UpdateHighestObjectId(sceneObject.ObjectId); + LiteNetLibIdentity[] sceneObjects = rootObjects[j].GetComponentsInChildren(true); + for (int k = 0; k < sceneObjects.Length; ++k) + { + LiteNetLibIdentity sceneObject = sceneObjects[k]; + if (sceneObject.ObjectId > 0) + { + sceneObject.gameObject.SetActive(false); + SceneObjects[sceneObject.ObjectId] = sceneObject; + LiteNetLibIdentity.UpdateHighestObjectId(sceneObject.ObjectId); + } + } } } } diff --git a/Scripts/GameApi/LiteNetLibGameManager.cs b/Scripts/GameApi/LiteNetLibGameManager.cs index a89d52e..ef2992e 100644 --- a/Scripts/GameApi/LiteNetLibGameManager.cs +++ b/Scripts/GameApi/LiteNetLibGameManager.cs @@ -319,8 +319,9 @@ await AddressableAssetDownloadManager.Download( // Wait until scene loaded while (!asyncOp.IsDone) { - await UniTask.NextFrame(); - Assets.onLoadSceneProgress.Invoke(serverSceneInfo.sceneName, false, isOnline, asyncOp.PercentComplete); + await UniTask.Yield(); + float percentageComplete = asyncOp.GetDownloadStatus().Percent; + Assets.onLoadSceneProgress.Invoke(serverSceneInfo.sceneName, false, isOnline, percentageComplete); } } else @@ -329,12 +330,14 @@ await AddressableAssetDownloadManager.Download( AsyncOperation asyncOp = SceneManager.LoadSceneAsync( serverSceneInfo.sceneName, new LoadSceneParameters(LoadSceneMode.Single)); + asyncOp.allowSceneActivation = false; // Wait until scene loaded - while (asyncOp != null && !asyncOp.isDone) + while (asyncOp.progress < 0.9f) { - await UniTask.NextFrame(); + await UniTask.Yield(); Assets.onLoadSceneProgress.Invoke(serverSceneInfo.sceneName, false, isOnline, asyncOp.progress); } + asyncOp.allowSceneActivation = true; } // If scene changed while loading, have to load the new one