chunk 1: core gameplay scripts scenes runtime assets
This commit is contained in:
347
Assets/Scripts/AssetBundleSystem/AssetBundleDownloadManager.cs
Normal file
347
Assets/Scripts/AssetBundleSystem/AssetBundleDownloadManager.cs
Normal file
@@ -0,0 +1,347 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using TMPro;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace CustomAssetBundleSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages AssetBundle downloads during LoadingScreen with UI feedback
|
||||
/// Checks cache, downloads if needed, handles offline mode
|
||||
/// </summary>
|
||||
public class AssetBundleDownloadManager : MonoBehaviour
|
||||
{
|
||||
[Header("UI References")]
|
||||
[SerializeField] private Slider loadingSlider;
|
||||
[SerializeField] private TextMeshProUGUI loadingText;
|
||||
[SerializeField] private TextMeshProUGUI hintsText;
|
||||
[SerializeField] private GameObject noInternetPanel; // Optional: Shows when internet required but not available
|
||||
|
||||
[Header("Download Settings")]
|
||||
[SerializeField] private string[] bundlesToPreload = new[] { "gamescene" };
|
||||
[SerializeField] private float minDisplayTime = 2f; // Minimum time to show loading (for UX)
|
||||
|
||||
[Header("Hints")]
|
||||
[SerializeField] private string[] downloadHints = new[]
|
||||
{
|
||||
"Downloading game content...",
|
||||
"Preparing assets for better performance...",
|
||||
"First time setup - this only happens once!",
|
||||
"Future launches will be instant!"
|
||||
};
|
||||
|
||||
[SerializeField] private string[] cachedHints = new[]
|
||||
{
|
||||
"Complete Weekly Missions to gain XP",
|
||||
"Complete a 20 Wins streak to level up in Rank",
|
||||
"Missions change every Week"
|
||||
};
|
||||
|
||||
// State
|
||||
private bool _isDownloading = false;
|
||||
private bool _downloadComplete = false;
|
||||
private bool _hasInternet = true;
|
||||
private RemoteAssetBundleManager _bundleManager;
|
||||
|
||||
// Events
|
||||
public event Action<bool> OnDownloadComplete; // true = success, false = failed
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_bundleManager = RemoteAssetBundleManager.Instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start the download process - call this from LoadingScreen
|
||||
/// </summary>
|
||||
public IEnumerator StartDownloadProcess(Action<bool> onComplete = null)
|
||||
{
|
||||
if (_isDownloading)
|
||||
{
|
||||
Debug.LogWarning("[DownloadManager] Download already in progress");
|
||||
yield break;
|
||||
}
|
||||
|
||||
_isDownloading = true;
|
||||
_downloadComplete = false;
|
||||
float startTime = Time.time;
|
||||
|
||||
Debug.Log("[DownloadManager] Starting AssetBundle download process...");
|
||||
|
||||
// Step 1: Initialize RemoteAssetBundleManager (downloads catalog)
|
||||
yield return InitializeBundleSystem();
|
||||
|
||||
if (!_bundleManager.IsInitialized)
|
||||
{
|
||||
Debug.LogError("[DownloadManager] Failed to initialize bundle system");
|
||||
HandleDownloadFailed("Failed to connect to server");
|
||||
onComplete?.Invoke(false);
|
||||
OnDownloadComplete?.Invoke(false);
|
||||
yield break;
|
||||
}
|
||||
|
||||
// Step 2: Check if bundles are already cached
|
||||
bool allCached = CheckIfBundlesCached();
|
||||
|
||||
if (allCached)
|
||||
{
|
||||
Debug.Log("[DownloadManager] ✓ All bundles already cached! (Offline play available)");
|
||||
UpdateUI(1f, "Ready!", cachedHints);
|
||||
|
||||
// Show success for minimum display time
|
||||
float elapsed = Time.time - startTime;
|
||||
if (elapsed < minDisplayTime)
|
||||
{
|
||||
yield return new WaitForSeconds(minDisplayTime - elapsed);
|
||||
}
|
||||
|
||||
_downloadComplete = true;
|
||||
_isDownloading = false;
|
||||
onComplete?.Invoke(true);
|
||||
OnDownloadComplete?.Invoke(true);
|
||||
yield break;
|
||||
}
|
||||
|
||||
// Step 3: Need to download - check internet connectivity
|
||||
_hasInternet = Application.internetReachability != NetworkReachability.NotReachable;
|
||||
|
||||
if (!_hasInternet)
|
||||
{
|
||||
Debug.LogWarning("[DownloadManager] No internet connection and bundles not cached");
|
||||
HandleNoInternet();
|
||||
onComplete?.Invoke(false);
|
||||
OnDownloadComplete?.Invoke(false);
|
||||
yield break;
|
||||
}
|
||||
|
||||
// Step 4: Download bundles with progress updates
|
||||
Debug.Log($"[DownloadManager] Downloading {bundlesToPreload.Length} bundle(s)...");
|
||||
UpdateUI(0f, "Downloading game content", downloadHints);
|
||||
|
||||
bool downloadSuccess = true;
|
||||
int bundleIndex = 0;
|
||||
|
||||
foreach (string bundleName in bundlesToPreload)
|
||||
{
|
||||
bundleIndex++;
|
||||
Debug.Log($"[DownloadManager] Downloading bundle {bundleIndex}/{bundlesToPreload.Length}: {bundleName}");
|
||||
|
||||
bool bundleLoaded = false;
|
||||
float bundleProgress = 0f;
|
||||
|
||||
// Subscribe to progress updates
|
||||
void ProgressHandler(string name, float progress)
|
||||
{
|
||||
if (name == bundleName)
|
||||
{
|
||||
bundleProgress = progress;
|
||||
float overallProgress = (bundleIndex - 1f + progress) / bundlesToPreload.Length;
|
||||
UpdateUI(overallProgress, $"Downloading {bundleName}", downloadHints);
|
||||
}
|
||||
}
|
||||
|
||||
_bundleManager.OnBundleDownloadProgress += ProgressHandler;
|
||||
|
||||
// Start download
|
||||
yield return _bundleManager.LoadBundleAsync(bundleName, (bundle) =>
|
||||
{
|
||||
bundleLoaded = (bundle != null);
|
||||
});
|
||||
|
||||
_bundleManager.OnBundleDownloadProgress -= ProgressHandler;
|
||||
|
||||
if (!bundleLoaded)
|
||||
{
|
||||
Debug.LogError($"[DownloadManager] Failed to download bundle: {bundleName}");
|
||||
downloadSuccess = false;
|
||||
break;
|
||||
}
|
||||
|
||||
Debug.Log($"[DownloadManager] ✓ Bundle '{bundleName}' ready!");
|
||||
}
|
||||
|
||||
if (!downloadSuccess)
|
||||
{
|
||||
HandleDownloadFailed("Failed to download game content");
|
||||
onComplete?.Invoke(false);
|
||||
OnDownloadComplete?.Invoke(false);
|
||||
yield break;
|
||||
}
|
||||
|
||||
// Step 5: Success!
|
||||
UpdateUI(1f, "Download complete!", downloadHints);
|
||||
Debug.Log("[DownloadManager] ✓ All bundles downloaded and cached successfully!");
|
||||
|
||||
// Show success for minimum display time
|
||||
float totalElapsed = Time.time - startTime;
|
||||
if (totalElapsed < minDisplayTime)
|
||||
{
|
||||
yield return new WaitForSeconds(minDisplayTime - totalElapsed);
|
||||
}
|
||||
|
||||
_downloadComplete = true;
|
||||
_isDownloading = false;
|
||||
onComplete?.Invoke(true);
|
||||
OnDownloadComplete?.Invoke(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the bundle system (downloads catalog)
|
||||
/// </summary>
|
||||
private IEnumerator InitializeBundleSystem()
|
||||
{
|
||||
Debug.Log("[DownloadManager] Initializing bundle system...");
|
||||
UpdateUI(0.05f, "Connecting to server", downloadHints);
|
||||
|
||||
yield return _bundleManager.InitializeAsync();
|
||||
|
||||
if (_bundleManager.IsInitialized)
|
||||
{
|
||||
Debug.Log("[DownloadManager] ✓ Bundle system initialized");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if all required bundles are already cached
|
||||
/// </summary>
|
||||
private bool CheckIfBundlesCached()
|
||||
{
|
||||
foreach (string bundleName in bundlesToPreload)
|
||||
{
|
||||
if (!_bundleManager.IsBundleCached(bundleName))
|
||||
{
|
||||
Debug.Log($"[DownloadManager] Bundle '{bundleName}' not cached - download required");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update UI elements with progress and hints
|
||||
/// </summary>
|
||||
private void UpdateUI(float progress, string statusText, string[] hints)
|
||||
{
|
||||
if (loadingSlider != null)
|
||||
{
|
||||
loadingSlider.value = progress;
|
||||
}
|
||||
|
||||
if (loadingText != null)
|
||||
{
|
||||
loadingText.text = statusText;
|
||||
}
|
||||
|
||||
if (hintsText != null && hints != null && hints.Length > 0)
|
||||
{
|
||||
// Show random hint or cycle through them
|
||||
int hintIndex = Mathf.FloorToInt(progress * hints.Length);
|
||||
hintIndex = Mathf.Clamp(hintIndex, 0, hints.Length - 1);
|
||||
hintsText.text = hints[hintIndex];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle no internet connection scenario
|
||||
/// </summary>
|
||||
private void HandleNoInternet()
|
||||
{
|
||||
Debug.LogWarning("[DownloadManager] ⚠️ No internet connection!");
|
||||
|
||||
if (loadingText != null)
|
||||
{
|
||||
loadingText.text = "No Internet Connection";
|
||||
}
|
||||
|
||||
if (hintsText != null)
|
||||
{
|
||||
hintsText.text = "Please connect to the internet to download game content";
|
||||
}
|
||||
|
||||
if (noInternetPanel != null)
|
||||
{
|
||||
noInternetPanel.SetActive(true);
|
||||
}
|
||||
|
||||
// Don't proceed - block user until they have internet
|
||||
_isDownloading = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle download failure
|
||||
/// </summary>
|
||||
private void HandleDownloadFailed(string errorMessage)
|
||||
{
|
||||
Debug.LogError($"[DownloadManager] Download failed: {errorMessage}");
|
||||
|
||||
if (loadingText != null)
|
||||
{
|
||||
loadingText.text = "Download Failed";
|
||||
}
|
||||
|
||||
if (hintsText != null)
|
||||
{
|
||||
hintsText.text = errorMessage;
|
||||
}
|
||||
|
||||
_isDownloading = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if download is complete and successful
|
||||
/// </summary>
|
||||
public bool IsDownloadComplete()
|
||||
{
|
||||
return _downloadComplete;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retry button handler (for no internet panel)
|
||||
/// </summary>
|
||||
public void RetryDownload()
|
||||
{
|
||||
if (noInternetPanel != null)
|
||||
{
|
||||
noInternetPanel.SetActive(false);
|
||||
}
|
||||
|
||||
// Restart the download process
|
||||
StartCoroutine(StartDownloadProcess());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get cache status for UI display
|
||||
/// </summary>
|
||||
public string GetCacheStatus()
|
||||
{
|
||||
if (!_bundleManager.IsInitialized)
|
||||
{
|
||||
return "Not initialized";
|
||||
}
|
||||
|
||||
int cachedCount = 0;
|
||||
foreach (string bundleName in bundlesToPreload)
|
||||
{
|
||||
if (_bundleManager.IsBundleCached(bundleName))
|
||||
{
|
||||
cachedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (cachedCount == bundlesToPreload.Length)
|
||||
{
|
||||
return "All content cached (Offline play available)";
|
||||
}
|
||||
else if (cachedCount > 0)
|
||||
{
|
||||
return $"{cachedCount}/{bundlesToPreload.Length} bundles cached";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Download required";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user