97 lines
3.2 KiB
C#
97 lines
3.2 KiB
C#
using System;
|
|
using Cysharp.Threading.Tasks;
|
|
using UnityEngine;
|
|
using UnityEngine.AddressableAssets;
|
|
using UnityEngine.ResourceManagement.AsyncOperations;
|
|
|
|
namespace BrewMonster.Scripts
|
|
{
|
|
/// <summary>
|
|
/// Single entry for <see cref="Addressables.InitializeAsync"/> after <see cref="GameContentBootstrap"/> gate
|
|
/// (version fetch + optional <see cref="AddressablesRuntimeUrlRewriter"/>). Prevents early init from UI code
|
|
/// (e.g. <c>AUIManager</c>) hitting remote URLs before CDN rewrite.
|
|
/// </summary>
|
|
public static class AddressablesInitService
|
|
{
|
|
static readonly object s_lock = new();
|
|
static UniTaskCompletionSource<bool> s_initTcs;
|
|
static bool s_initialized;
|
|
|
|
public static bool IsInitialized => s_initialized;
|
|
|
|
/// <summary>
|
|
/// Waits bootstrap gate, then initializes Addressables once.
|
|
/// </summary>
|
|
public static async UniTask EnsureInitializedAsync()
|
|
{
|
|
if (s_initialized)
|
|
return;
|
|
|
|
UniTaskCompletionSource<bool> waiter;
|
|
lock (s_lock)
|
|
{
|
|
if (s_initialized)
|
|
return;
|
|
|
|
if (s_initTcs != null)
|
|
{
|
|
waiter = s_initTcs;
|
|
}
|
|
else
|
|
{
|
|
waiter = new UniTaskCompletionSource<bool>();
|
|
s_initTcs = waiter;
|
|
}
|
|
}
|
|
|
|
if (waiter != s_initTcs)
|
|
{
|
|
await waiter.Task;
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
if (!GameContentBootstrapSession.IsContentReady)
|
|
await GameContentBootstrap.WaitForPreAddressablesSetupIfAnyAsync();
|
|
else
|
|
Debug.Log("[Cuong] AddressablesInitService: Content scene đã sync — bỏ chờ gate.");
|
|
|
|
Debug.Log("[Cuong] AddressablesInitService: InitializeAsync...");
|
|
|
|
var handle = Addressables.InitializeAsync();
|
|
await handle.ToUniTask();
|
|
|
|
if (handle.Status != AsyncOperationStatus.Succeeded)
|
|
{
|
|
var msg = handle.OperationException?.Message ?? "InitializeAsync failed";
|
|
waiter.TrySetException(new InvalidOperationException(msg));
|
|
lock (s_lock)
|
|
s_initTcs = null;
|
|
throw handle.OperationException ?? new InvalidOperationException(msg);
|
|
}
|
|
|
|
s_initialized = true;
|
|
waiter.TrySetResult(true);
|
|
Debug.Log("[Cuong] AddressablesInitService: InitializeAsync xong.");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
if (!waiter.Task.Status.IsCompleted())
|
|
waiter.TrySetException(ex);
|
|
lock (s_lock)
|
|
s_initTcs = null;
|
|
throw;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sync wait for legacy <c>Init()</c> paths. Prefer async when possible.
|
|
/// </summary>
|
|
public static void EnsureInitializedBlocking()
|
|
{
|
|
EnsureInitializedAsync().GetAwaiter().GetResult();
|
|
}
|
|
}
|
|
}
|