Files
ichni_Official/Assets/Scripts/Settings/LocalizationBootstrap.cs
SoulliesOfficial fe00ecfcc7 微调
2026-07-24 03:43:11 -04:00

159 lines
5.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections;
using Ichni.Diagnostics;
using UnityEngine;
using UnityEngine.Localization.Settings;
using UnityEngine.ResourceManagement.AsyncOperations;
namespace Ichni
{
/// <summary>
/// Unity Localization 的统一启动入口。
/// <para>
/// 本类只包装 Unity 官方提供的 <see cref="LocalizationSettings.InitializationOperation"/>
/// 不自行初始化 Addressables、不查询 Locale Label也不复制 Localization Package 的内部加载流程。
/// 因此 Settings、Yarn 与其它本地化消费者始终等待同一个由 Unity 管理的初始化操作。
/// </para>
/// </summary>
public static class LocalizationBootstrap
{
public enum InitializationState
{
NotStarted,
Initializing,
Ready,
Failed
}
private static AsyncOperationHandle<LocalizationSettings> _initializationOperation;
public static InitializationState State { get; private set; } = InitializationState.NotStarted;
public static bool IsReady => State == InitializationState.Ready;
public static bool HasFailed => State == InitializationState.Failed;
public static string FailureReason { get; private set; }
/// <summary>
/// Unity Localization 官方初始化 Handle。
/// 获取该属性会以幂等方式启动初始化,但不会同步阻塞主线程。
/// </summary>
public static AsyncOperationHandle<LocalizationSettings> InitializationOperation
{
get
{
BeginInitialization();
return _initializationOperation;
}
}
/// <summary>
/// 在关闭 Domain Reload 的 Editor 配置下,清理上一次 Play Mode 留下的项目侧状态。
/// Localization Package 会自行重建其内部 Handle本类不持有也不释放 Package 的资源。
/// </summary>
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void ResetState()
{
_initializationOperation = default;
State = InitializationState.NotStarted;
FailureReason = null;
}
/// <summary>
/// 按 Unity 官方流程获取唯一的 Localization 初始化操作。
/// 可以由多个系统重复调用;已经启动后不会创建第二条加载链。
/// </summary>
public static void BeginInitialization()
{
if (State != InitializationState.NotStarted)
{
return;
}
try
{
// 不设置 InitializeSynchronously也不直接访问 SelectedLocale。
// InitializationOperation 会异步完成 Locale 选择及所有配置为 Preload 的数据库初始化。
_initializationOperation = LocalizationSettings.InitializationOperation;
State = InitializationState.Initializing;
Log("开始等待 Unity Localization 官方 InitializationOperation。");
RefreshState();
}
catch (Exception exception)
{
Fail("无法创建 Unity Localization 初始化操作。", exception);
}
}
/// <summary>
/// 刷新初始化结果。供 YarnTask 等不能直接 yield AsyncOperationHandle 的异步流程调用。
/// </summary>
public static void RefreshState()
{
if (State != InitializationState.Initializing)
{
return;
}
if (!_initializationOperation.IsValid())
{
Fail("Unity Localization 返回了无效的 InitializationOperation Handle。");
return;
}
if (!_initializationOperation.IsDone)
{
return;
}
if (_initializationOperation.Status != AsyncOperationStatus.Succeeded)
{
Fail("Unity Localization 初始化失败。", _initializationOperation.OperationException);
return;
}
LocaleReady();
}
/// <summary>
/// 供 MonoBehaviour 协程等待 Unity Localization 初始化。
/// 此处直接 yield 官方 Handle不使用轮询超时或自建 Addressables 状态机。
/// </summary>
public static IEnumerator WaitForInitialization()
{
BeginInitialization();
if (State == InitializationState.Initializing)
{
yield return _initializationOperation;
RefreshState();
}
}
private static void LocaleReady()
{
State = InitializationState.Ready;
FailureReason = null;
// SelectedLocale 只有在完整 InitializationOperation 成功后才允许同步读取。
string localeCode = LocalizationSettings.SelectedLocale != null
? LocalizationSettings.SelectedLocale.Identifier.Code
: "<null>";
Log($"Unity Localization 初始化完成。SelectedLocale={localeCode}");
}
private static void Fail(string message, Exception exception = null)
{
FailureReason = exception == null ? message : $"{message} Exception={exception}";
State = InitializationState.Failed;
Debug.LogError($"[LocalizationBootstrap] {FailureReason}");
BuildHangTracer.Log("LOCALIZATION_BOOTSTRAP", $"[Failed] {FailureReason}");
}
private static void Log(string message)
{
Debug.Log($"[LocalizationBootstrap] {message}");
BuildHangTracer.Log("LOCALIZATION_BOOTSTRAP", message);
}
}
}