Files
2026-05-21 17:42:02 +07:00

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();
}
}
}