현지화 로직 수정

This commit is contained in:
NTG 2025-08-17 21:56:34 +09:00
parent 56b5f3a701
commit 6c08cb3537
2 changed files with 124 additions and 35 deletions

View File

@ -97,7 +97,7 @@ public string GetString(string key)
var entryRef = key;
var locale = LocalizationSettings.SelectedLocale;
VariablesGroupAsset variables = SmartStringVariables.Instance.GetVariablesGroupAsset();
VariablesGroupAsset variables = GameDataSo.instance.GameLocalizationData.SmartStringVariableGroup;
if (variables != null)
{
_singleArgBuffer.Clear();

View File

@ -1,39 +1,128 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Localization.SmartFormat.PersistentVariables;
namespace DDD
{
/// <summary>
/// Smart String 변수 전담 매니저.
/// - VariablesGroupAsset 안의 변수들을 생성/재사용하고 값만 갱신(무가비지).
/// - {day}, {playerName}, {money} 등 공용 Set API 제공.
/// </summary>
public class SmartStringVariables : Singleton<SmartStringVariables>, IManager
[Flags]
public enum SmartVariablesDomain : uint
{
private VariablesGroupAsset _vars;
private GameStateSo _gameStateSo;
None = 0u,
RestaurantToday = 1u << 0,
ChecklistTargets = 1u << 1,
PlayerLevel = 1u << 2,
All = 0xFFFFFFFFu,
}
private const string VariablesGroupAssetKey = "SmartStringGroup";
private const string Daykey = "day";
public enum smartStringKey
{
None = 0,
Day,
AddedTodayFoodCount,
AddedTodayCookwareCount,
MatchedTodayMenuWithCookwareCount,
ChecklistFoodCount,
ChecklistCookwareCount,
ChecklistMatchedMenuWithCookwareCount,
}
public class SmartStringVariables : Singleton<SmartStringVariables>, IManager, IEventHandler<SmartVariablesDirtyEvent>
{
private Dictionary<smartStringKey, string> _smartStringKeys = new()
{
{smartStringKey.Day, "day"},
{smartStringKey.AddedTodayFoodCount, "addedTodayFoodCount"},
{smartStringKey.AddedTodayCookwareCount, "addedTodayCookwareCount"},
{smartStringKey.MatchedTodayMenuWithCookwareCount, "matchedTodayMenuWithCookwareCount"},
{smartStringKey.ChecklistFoodCount, "checklistFoodCount"},
{smartStringKey.ChecklistCookwareCount, "checklistCookwareCount"},
{smartStringKey.ChecklistMatchedMenuWithCookwareCount, "checklistMatchedMenuWithCookwareCount"},
};
private void OnDestroy()
{
EventBus.Unregister<SmartVariablesDirtyEvent>(this);
}
public void PreInit() { }
public async Task Init()
{
_vars = await AssetManager.LoadAsset<VariablesGroupAsset>(VariablesGroupAssetKey);
Debug.Assert(_vars != null, "_variablesGroupAsset is null");
_gameStateSo = await AssetManager.LoadAsset<GameStateSo>(DataConstants.GameStateSo);
Debug.Assert(_gameStateSo != null, "_gameStateSo is null");
var gameLevelStateSo = GameStateSo.instance.GameLevelStateSo;
var restaurantStateSo = RestaurantState.instance.ManagementState;
// 예시: day 초기 세팅 (없으면 생성, 타입 다르면 교체)
Set(Daykey, _gameStateSo.GetCurrentLevel());
Set(_smartStringKeys[smartStringKey.Day], gameLevelStateSo.Level);
Set(_smartStringKeys[smartStringKey.AddedTodayFoodCount], restaurantStateSo.AddedTodayFoodCount);
Set(_smartStringKeys[smartStringKey.AddedTodayCookwareCount], restaurantStateSo.AddedTodayCookwareCount);
Set(_smartStringKeys[smartStringKey.MatchedTodayMenuWithCookwareCount], restaurantStateSo.MatchedTodayMenuWithCookwareCount);
Set(_smartStringKeys[smartStringKey.ChecklistFoodCount], restaurantStateSo.ChecklistFoodCount);
Set(_smartStringKeys[smartStringKey.ChecklistCookwareCount], restaurantStateSo.ChecklistCookwareCount);
Set(_smartStringKeys[smartStringKey.ChecklistMatchedMenuWithCookwareCount], restaurantStateSo.ChecklistMatchedMenuWithCookwareCount);
await Task.CompletedTask;
}
public void PostInit() { }
public void PostInit()
{
// 도메인 단위 더티 이벤트를 구독하여 필요한 key만 갱신
EventBus.Register<SmartVariablesDirtyEvent>(this);
}
public VariablesGroupAsset GetVariablesGroupAsset() => _vars;
private RestaurantManagementStateSo GetRestaurantState() => RestaurantState.instance.ManagementState;
public void Invoke(SmartVariablesDirtyEvent evt)
{
var flags = evt.DomainFlags;
if (flags == SmartVariablesDomain.All)
{
RefreshAll();
return;
}
if ((flags & SmartVariablesDomain.RestaurantToday) != 0)
{
RefreshTodayMenuCounts();
}
if ((flags & SmartVariablesDomain.ChecklistTargets) != 0)
{
RefreshChecklistTargets();
}
if ((flags & SmartVariablesDomain.PlayerLevel) != 0)
{
RefreshDay();
}
}
public void RefreshTodayMenuCounts()
{
var state = GetRestaurantState();
Set(_smartStringKeys[smartStringKey.AddedTodayFoodCount], state.AddedTodayFoodCount);
Set(_smartStringKeys[smartStringKey.AddedTodayCookwareCount], state.AddedTodayCookwareCount);
Set(_smartStringKeys[smartStringKey.MatchedTodayMenuWithCookwareCount], state.MatchedTodayMenuWithCookwareCount);
}
public void RefreshChecklistTargets()
{
var state = GetRestaurantState();
Set(_smartStringKeys[smartStringKey.ChecklistFoodCount], state.ChecklistFoodCount);
Set(_smartStringKeys[smartStringKey.ChecklistCookwareCount], state.ChecklistCookwareCount);
Set(_smartStringKeys[smartStringKey.ChecklistMatchedMenuWithCookwareCount], state.ChecklistMatchedMenuWithCookwareCount);
}
public void RefreshDay()
{
var gameLevelStateSo = GameStateSo.instance.GameLevelStateSo;
Set(_smartStringKeys[smartStringKey.Day], gameLevelStateSo.Level);
}
public void RefreshAll()
{
RefreshDay();
RefreshTodayMenuCounts();
RefreshChecklistTargets();
}
// ---------- 공용 Set API (가비지 최소화) ----------
@ -48,7 +137,7 @@ public void Set(string key, int value)
public void Set(string key, float value)
{
var v = Ensure<FloatVariable>(key);
if (!Mathf.Approximately(v.Value, value)) v.Value = value;
if (Mathf.Approximately(v.Value, value) == false) v.Value = value;
}
/// <summary>bool 변수 세팅. {key} 로 접근.</summary>
@ -62,7 +151,7 @@ public void Set(string key, bool value)
public void Set(string key, string value)
{
var v = Ensure<StringVariable>(key);
if (!string.Equals(v.Value, value)) v.Value = value;
if (string.Equals(v.Value, value) == false) v.Value = value;
}
/// <summary>
@ -73,7 +162,7 @@ public void SetEnum<TEnum>(string key, TEnum value) where TEnum : struct
{
var v = Ensure<StringVariable>(key);
string s = value.ToString();
if (!string.Equals(v.Value, s)) v.Value = s;
if (string.Equals(v.Value, s) == false) v.Value = s;
}
// ---------- 유틸 ----------
@ -84,24 +173,24 @@ public void SetEnum<TEnum>(string key, TEnum value) where TEnum : struct
/// </summary>
private T Ensure<T>(string key) where T : class, IVariable, new()
{
Debug.Assert(!string.IsNullOrEmpty(key), "SmartStringVariables.Ensure: key is null or empty.");
Debug.Assert(_vars != null, "SmartStringVariables.Ensure: _vars is null (Init 순서 확인).");
if (_vars.TryGetValue(key, out var existing))
if (string.IsNullOrWhiteSpace(key))
{
if (existing is T ok) return ok;
_vars.Remove(key); // 타입 다르면 제거 후 교체
Debug.LogError("SmartStringVariables.Ensure: key is null or empty.");
return null;
}
var smartStringVariableGroup = GameDataSo.instance.GameLocalizationData.SmartStringVariableGroup;
if (smartStringVariableGroup.TryGetValue(key, out var existing))
{
if (existing is T hasType) return hasType;
smartStringVariableGroup.Remove(key); // 타입 다르면 제거 후 교체
}
var created = new T();
_vars.Add(key, created);
smartStringVariableGroup.Add(key, created);
return (T)created;
}
/// <summary>변수 존재 여부.</summary>
public bool Has(string key) => _vars != null && _vars.ContainsKey(key);
/// <summary>변수 제거.</summary>
public bool Remove(string key) => _vars != null && _vars.Remove(key);
}
}