UI换了很多,spine主视觉停用

This commit is contained in:
FloatGaming
2026-06-15 20:17:25 +08:00
parent 5eec879582
commit 216ab08e8d
3634 changed files with 814422 additions and 382766 deletions
@@ -70,6 +70,7 @@ public sealed class DushMaterialLedger : MonoBehaviour
loadedFromSave = DushMaterialLedgerStorage.TryLoad(out payload);
RebuildFromPayload(payload);
initialized = true;
TryRecoverFromDefaultPlayerData();
SyncMirrorCounts();
SaveNow();
}
@@ -278,6 +279,46 @@ public sealed class DushMaterialLedger : MonoBehaviour
}
}
private bool TryRecoverFromDefaultPlayerData()
{
Player_SO player = RuntimeResourcesCache.LoadDefaultPlayerSo();
if (player == null)
{
return false;
}
bool changed = false;
for (int i = 0; i < DushMaterialCatalog.All.Count; i++)
{
var descriptor = DushMaterialCatalog.All[i];
if (string.IsNullOrEmpty(descriptor.LegacyPlayerFieldName))
{
continue;
}
int legacyValue = Mathf.Max(0, player.GetLegacyDushMaterialCount(descriptor.LegacyPlayerFieldName));
if (legacyValue <= 0)
{
continue;
}
if (GetCountByKey(descriptor.Key) > 0)
{
continue;
}
countsByKey[descriptor.Key] = legacyValue;
changed = true;
}
if (changed)
{
Debug.LogWarning("[DushMaterialLedger] Recovered growth materials from Player_SO mirror fields.");
}
return changed;
}
private DushMaterialLedgerPayload BuildPayload()
{
var payload = DushMaterialLedgerStorage.CreateDefaultPayload();
@@ -76,6 +76,7 @@ public sealed class ExpBottleLedger : MonoBehaviour
loadedFromSave = ExpBottleLedgerStorage.TryLoad(out payload);
RebuildFromPayload(payload);
initialized = true;
TryRecoverFromDefaultPlayerData();
SyncMirrorCounts();
SaveNow();
if (OnLedgerReloaded != null)
@@ -421,6 +422,46 @@ public sealed class ExpBottleLedger : MonoBehaviour
}
}
private bool TryRecoverFromDefaultPlayerData()
{
Player_SO player = RuntimeResourcesCache.LoadDefaultPlayerSo();
if (player == null)
{
return false;
}
bool changed = false;
for (int i = 0; i < ExpBottleCatalog.All.Count; i++)
{
var descriptor = ExpBottleCatalog.All[i];
if (string.IsNullOrEmpty(descriptor.LegacyPlayerFieldName))
{
continue;
}
int legacyValue = Mathf.Max(0, player.GetLegacyExpBottleCount(descriptor.LegacyPlayerFieldName));
if (legacyValue <= 0)
{
continue;
}
if (GetCountByKey(descriptor.Key) > 0)
{
continue;
}
countsByKey[descriptor.Key] = legacyValue;
changed = true;
}
if (changed)
{
Debug.LogWarning("[ExpBottleLedger] Recovered bottle counts from Player_SO mirror fields.");
}
return changed;
}
private void SyncToPlayerData()
{
if (boundPlayerData == null)
@@ -0,0 +1,161 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public static class SceneObjectLookupCache
{
private static readonly Dictionary<string, GameObject> Cache = new Dictionary<string, GameObject>(StringComparer.Ordinal);
private static readonly Dictionary<Type, UnityEngine.Object> AnyTypeCache = new Dictionary<Type, UnityEngine.Object>();
private static readonly Dictionary<Type, UnityEngine.Object> FirstTypeCache = new Dictionary<Type, UnityEngine.Object>();
private static bool hooked;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void ResetStaticState()
{
Cache.Clear();
AnyTypeCache.Clear();
FirstTypeCache.Clear();
hooked = false;
}
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void Bootstrap()
{
if (hooked)
return;
hooked = true;
SceneManager.sceneLoaded -= OnSceneLoaded;
SceneManager.sceneLoaded += OnSceneLoaded;
SceneManager.activeSceneChanged -= OnActiveSceneChanged;
SceneManager.activeSceneChanged += OnActiveSceneChanged;
}
public static GameObject Find(string nameOrPath)
{
if (string.IsNullOrWhiteSpace(nameOrPath))
return null;
string key = nameOrPath.Trim();
if (Cache.TryGetValue(key, out GameObject cached))
{
if (IsUsableCachedGameObject(cached, key))
return cached;
Cache.Remove(key);
}
GameObject found = GameObject.Find(key);
if (found != null)
Cache[key] = found;
return found;
}
public static T FindComponent<T>(string nameOrPath) where T : Component
{
GameObject go = Find(nameOrPath);
return go != null ? go.GetComponent<T>() : null;
}
public static T FindAny<T>() where T : UnityEngine.Object
{
var type = typeof(T);
if (AnyTypeCache.TryGetValue(type, out var cached))
{
if (IsUsableCachedObject(cached))
return cached as T;
AnyTypeCache.Remove(type);
}
T found = UnityEngine.Object.FindAnyObjectByType<T>();
if (found != null)
AnyTypeCache[type] = found;
return found;
}
public static T FindFirst<T>() where T : UnityEngine.Object
{
var type = typeof(T);
if (FirstTypeCache.TryGetValue(type, out var cached))
{
if (IsUsableCachedObject(cached))
return cached as T;
FirstTypeCache.Remove(type);
}
T found = UnityEngine.Object.FindFirstObjectByType<T>();
if (found != null)
FirstTypeCache[type] = found;
return found;
}
public static Transform FindTransform(string nameOrPath)
{
GameObject go = Find(nameOrPath);
return go != null ? go.transform : null;
}
public static void Clear()
{
Cache.Clear();
AnyTypeCache.Clear();
FirstTypeCache.Clear();
}
private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
Cache.Clear();
AnyTypeCache.Clear();
FirstTypeCache.Clear();
}
private static void OnActiveSceneChanged(Scene oldScene, Scene newScene)
{
Cache.Clear();
AnyTypeCache.Clear();
FirstTypeCache.Clear();
}
private static bool IsUsableCachedObject(UnityEngine.Object cached)
{
if (cached == null)
return false;
if (cached is Component component)
return component != null && component.gameObject != null && component.gameObject.activeInHierarchy;
if (cached is GameObject go)
return go.activeInHierarchy;
return true;
}
private static bool IsUsableCachedGameObject(GameObject cached, string key)
{
if (cached == null || !cached.activeInHierarchy)
return false;
int slashIndex = key.IndexOf('/');
if (slashIndex < 0)
return cached.name == key;
return BuildHierarchyPath(cached.transform) == key;
}
private static string BuildHierarchyPath(Transform transform)
{
if (transform == null)
return string.Empty;
var path = transform.name;
while (transform.parent != null)
{
transform = transform.parent;
path = transform.name + "/" + path;
}
return path;
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4e16a58b0ef1c6649b98b3f1c2f604eb
@@ -18,71 +18,71 @@ public static class StoreExpBottlePurchaseService
if (playerData == null)
{
failureMessage = "玩家数据丢失";
failureMessage = LocalizationService.Get("store.error.player_data_missing", "玩家数据丢失");
return false;
}
if (itemSO == null)
{
failureMessage = "商品数据丢失";
failureMessage = LocalizationService.Get("store.error.item_data_missing", "商品数据丢失");
return false;
}
if (!itemSO.isOnShelf || !itemSO.canbepurchased)
{
failureMessage = "物品未上架";
failureMessage = LocalizationService.Get("store.error.item_not_on_shelf", "物品未上架");
return false;
}
if (packageCount <= 0)
{
failureMessage = "本店禁止无实物交易";
failureMessage = LocalizationService.Get("store.error.invalid_purchase_count", "本店禁止无实物交易");
return false;
}
if (RequiresSinglePurchase(itemSO) && packageCount > 1)
{
failureMessage = "该物品仅支持单份购买";
failureMessage = LocalizationService.Get("store.error.single_purchase_only", "该物品仅支持单份购买");
return false;
}
if (itemSO.costRequirements == null || itemSO.costRequirements.Count == 0)
{
failureMessage = "不可购买";
failureMessage = LocalizationService.Get("store.error.cannot_purchase", "不可购买");
return false;
}
var primaryCost = itemSO.costRequirements[0];
if (itemSO.associatedSelectableEquipmentRewardSource != null)
{
failureMessage = "该物品需要通过选择器购买";
failureMessage = LocalizationService.Get("store.error.selector_required", "该物品需要通过选择器购买");
return false;
}
if (!IsSupportedCurrency(primaryCost.currencyType))
{
failureMessage = "不可购买";
failureMessage = LocalizationService.Get("store.error.cannot_purchase", "不可购买");
return false;
}
long longGrantedCount = (long)Mathf.Max(1, itemSO.itemSinglePurchaseQty) * packageCount;
if (longGrantedCount > int.MaxValue)
{
failureMessage = "达到单次购买限额";
failureMessage = LocalizationService.Get("store.error.purchase_limit_per_transaction", "达到单次购买限额");
return false;
}
grantedCount = (int)longGrantedCount;
if (itemSO.itemPurchaseQuota >= 0 && itemSO.purchasedCount + grantedCount > itemSO.itemPurchaseQuota)
{
failureMessage = "超过限购额度";
failureMessage = LocalizationService.Get("store.error.purchase_quota_exceeded", "超过限购额度");
return false;
}
long totalCostLong = (long)primaryCost.amount * packageCount;
if (totalCostLong > int.MaxValue)
{
failureMessage = "达到单次购买限额";
failureMessage = LocalizationService.Get("store.error.purchase_limit_per_transaction", "达到单次购买限额");
return false;
}
@@ -97,13 +97,13 @@ public static class StoreExpBottlePurchaseService
if (!HasEnoughCurrency(primaryCost.currencyType, totalCost))
{
failureMessage = "货币不足";
failureMessage = LocalizationService.Get("store.error.insufficient_currency", "货币不足");
return false;
}
if (!TrySpendCurrency(primaryCost.currencyType, totalCost))
{
failureMessage = "货币不足";
failureMessage = LocalizationService.Get("store.error.insufficient_currency", "货币不足");
return false;
}
@@ -134,7 +134,7 @@ public static class StoreExpBottlePurchaseService
failureMessage = string.Empty;
if (itemSO == null)
{
failureMessage = "商品数据丢失";
failureMessage = LocalizationService.Get("store.error.item_data_missing", "商品数据丢失");
return false;
}
@@ -147,7 +147,7 @@ public static class StoreExpBottlePurchaseService
EquipmentConsumableKind equipmentConsumableKind;
if (!TryResolveConsumableGrant(itemSO, out grantType, out bottleKind, out materialKind, out equipmentConsumableKind))
{
failureMessage = "当前未配置发放逻辑";
failureMessage = LocalizationService.Get("store.error.grant_logic_missing", "当前未配置发放逻辑");
return false;
}
return true;
@@ -158,7 +158,7 @@ public static class StoreExpBottlePurchaseService
return StoreOwnershipLedger.EnsureInstance().TryGrantOwnershipPreview(itemSO, out failureMessage);
default:
failureMessage = "当前未配置发放逻辑";
failureMessage = LocalizationService.Get("store.error.grant_logic_missing", "当前未配置发放逻辑");
return false;
}
}
@@ -168,7 +168,7 @@ public static class StoreExpBottlePurchaseService
failureMessage = string.Empty;
if (itemSO == null)
{
failureMessage = "商品数据丢失";
failureMessage = LocalizationService.Get("store.error.item_data_missing", "商品数据丢失");
return false;
}
@@ -181,7 +181,7 @@ public static class StoreExpBottlePurchaseService
EquipmentConsumableKind equipmentConsumableKind;
if (!TryResolveConsumableGrant(itemSO, out grantType, out bottleKind, out materialKind, out equipmentConsumableKind))
{
failureMessage = "当前未配置发放逻辑";
failureMessage = LocalizationService.Get("store.error.grant_logic_missing", "当前未配置发放逻辑");
return false;
}
@@ -205,7 +205,7 @@ public static class StoreExpBottlePurchaseService
return true;
}
failureMessage = "当前未配置发放逻辑";
failureMessage = LocalizationService.Get("store.error.grant_logic_missing", "当前未配置发放逻辑");
return false;
case storeItemSO.ItemType.character:
@@ -214,7 +214,7 @@ public static class StoreExpBottlePurchaseService
return StoreOwnershipLedger.EnsureInstance().TryGrantOwnership(itemSO, out failureMessage);
default:
failureMessage = "当前未配置发放逻辑";
failureMessage = LocalizationService.Get("store.error.grant_logic_missing", "当前未配置发放逻辑");
return false;
}
}
@@ -223,7 +223,7 @@ public static class StoreExpBottlePurchaseService
{
var builder = new StringBuilder();
builder.Append("[StorePurchase] 已成功购买:");
builder.Append(itemSO != null ? itemSO.itemName : "未知物品");
builder.Append(itemSO != null ? itemSO.itemName : LocalizationService.Get("item.unknown.store_item", "Unknown Item"));
builder.Append(" | 花费Coins=");
builder.Append(totalCost);
builder.Append(" | 发放数量=");
@@ -71,11 +71,21 @@ public sealed class StoreOwnershipLedger : MonoBehaviour
initialized = true;
StoreOwnershipPayload payload;
StoreOwnershipStorage.TryLoad(out payload);
bool loadedFromSave = StoreOwnershipStorage.TryLoad(out payload);
RebuildFromPayload(payload);
LoadStoreItems();
SyncAllMirrorFlags();
SaveNow();
bool recoveredFromMirrors = false;
if (!loadedFromSave)
{
recoveredFromMirrors = SeedFromCurrentMirrorFlags();
}
if (loadedFromSave || recoveredFromMirrors)
{
SyncAllMirrorFlags();
SaveNow();
}
}
public void ForceSyncMirrorFlags()
@@ -132,7 +142,7 @@ public sealed class StoreOwnershipLedger : MonoBehaviour
break;
default:
failureMessage = "当前未配置发放逻辑";
failureMessage = LocalizationService.Get("store.error.grant_logic_missing", "当前未配置发放逻辑");
return false;
}
@@ -149,7 +159,7 @@ public sealed class StoreOwnershipLedger : MonoBehaviour
if (itemSO == null)
{
failureMessage = "商品数据丢失";
failureMessage = LocalizationService.Get("store.error.item_data_missing", "商品数据丢失");
return false;
}
@@ -255,7 +265,7 @@ public sealed class StoreOwnershipLedger : MonoBehaviour
}
}
private void SeedFromCurrentMirrorFlags()
private bool SeedFromCurrentMirrorFlags()
{
bool changed = false;
for (int i = 0; i < cachedStoreItems.Count; i++)
@@ -276,10 +286,7 @@ public sealed class StoreOwnershipLedger : MonoBehaviour
changed = true;
}
if (changed)
{
SaveNow();
}
return changed;
}
private StoreOwnershipEntry TrySeedEntry(storeItemSO itemSO)
@@ -446,13 +453,13 @@ public sealed class StoreOwnershipLedger : MonoBehaviour
failureMessage = string.Empty;
if (itemSO == null)
{
failureMessage = "商品数据丢失";
failureMessage = LocalizationService.Get("store.error.item_data_missing", "商品数据丢失");
return false;
}
if (IsOwned(itemSO))
{
failureMessage = "物品已解锁";
failureMessage = LocalizationService.Get("store.error.item_already_unlocked", "物品已解锁");
return false;
}
@@ -461,7 +468,7 @@ public sealed class StoreOwnershipLedger : MonoBehaviour
case storeItemSO.ItemType.character:
if (itemSO.associatedAllyHero == null)
{
failureMessage = "角色数据未配置";
failureMessage = LocalizationService.Get("store.error.character_data_missing", "角色数据未配置");
return false;
}
return true;
@@ -469,7 +476,7 @@ public sealed class StoreOwnershipLedger : MonoBehaviour
case storeItemSO.ItemType.song:
if (itemSO.associatedSong == null)
{
failureMessage = "歌曲数据未配置";
failureMessage = LocalizationService.Get("store.error.song_data_missing", "歌曲数据未配置");
return false;
}
return true;
@@ -477,7 +484,7 @@ public sealed class StoreOwnershipLedger : MonoBehaviour
case storeItemSO.ItemType.storyPassage:
if (itemSO.associatedStoryPassage == null)
{
failureMessage = "剧情数据未配置";
failureMessage = LocalizationService.Get("store.error.story_data_missing", "剧情数据未配置");
return false;
}
@@ -485,14 +492,14 @@ public sealed class StoreOwnershipLedger : MonoBehaviour
{
if (itemSO.associatedStorySonId < 0 || FindStorySonIndex(itemSO.associatedStoryPassage, itemSO.associatedStorySonId) < 0)
{
failureMessage = "剧情子章节未配置";
failureMessage = LocalizationService.Get("store.error.story_chapter_missing", "剧情子章节未配置");
return false;
}
}
return true;
default:
failureMessage = "当前未配置发放逻辑";
failureMessage = LocalizationService.Get("store.error.grant_logic_missing", "当前未配置发放逻辑");
return false;
}
}