233 lines
8.5 KiB
C#
233 lines
8.5 KiB
C#
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
public class InGamePerformanceManager : MonoBehaviour
|
|
{
|
|
public static InGamePerformanceManager Instance { get; private set; }
|
|
|
|
[Header("成就库")]
|
|
[Tooltip("在 Resources/Achievements 目录下的所有成就资源")]
|
|
private List<InGameAchievementSO> achievementLibrary = new List<InGameAchievementSO>();
|
|
|
|
[Header("结算展示配置")]
|
|
public GameObject archievePrefab; // 通用成就预制体
|
|
public GameObject place_to_putdown; // 默认实例化容器
|
|
|
|
[System.Serializable]
|
|
public class CategoryDisplayMapping
|
|
{
|
|
public AchievementCategory category;
|
|
public GameObject parent;
|
|
}
|
|
public List<CategoryDisplayMapping> categoryDisplays = new List<CategoryDisplayMapping>();
|
|
|
|
// 记录每个分类下达成的最高成就及其来源 SO
|
|
private class UnlockedAchievementInfo
|
|
{
|
|
public AchievementLevel level;
|
|
public InGameAchievementSO sourceSO;
|
|
}
|
|
|
|
private Dictionary<AchievementCategory, UnlockedAchievementInfo> unlockedAchievements = new Dictionary<AchievementCategory, UnlockedAchievementInfo>();
|
|
|
|
private void Awake()
|
|
{
|
|
Debug.Log("[PerformanceManager] Awake called");
|
|
if (Instance == null)
|
|
{
|
|
Instance = this;
|
|
LoadAchievementLibrary();
|
|
}
|
|
else
|
|
{
|
|
Destroy(gameObject);
|
|
}
|
|
}
|
|
|
|
private void LoadAchievementLibrary()
|
|
{
|
|
// 尝试从 Resources/Achievements 加载
|
|
var loaded = Resources.LoadAll<InGameAchievementSO>("Achievements");
|
|
|
|
// 如果根目录没找到,尝试在整个 Resources 中搜索
|
|
if (loaded == null || loaded.Length == 0)
|
|
{
|
|
loaded = Resources.LoadAll<InGameAchievementSO>("");
|
|
}
|
|
|
|
if (loaded != null && loaded.Length > 0)
|
|
{
|
|
achievementLibrary.Clear();
|
|
// 过滤掉可能重复加载的 SO(如果是在根目录搜索)
|
|
foreach (var so in loaded)
|
|
{
|
|
if (!achievementLibrary.Contains(so))
|
|
achievementLibrary.Add(so);
|
|
}
|
|
Debug.Log($"[PerformanceManager] 扫描成功!已加载 {achievementLibrary.Count} 个分类配置文件");
|
|
|
|
foreach (var a in achievementLibrary)
|
|
{
|
|
Debug.Log($" - 分类: {a.category} (ID: {a.achievementID}, Type: {a.achievementType}), 包含 {a.levels.Count} 个等级");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("[PerformanceManager] 关键错误:未在 Resources 路径下找到任何 InGameAchievementSO 资源!请确保 SO 文件位于 Resources 文件夹内。");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 更新当前 Combo 数并检查相关成就
|
|
/// </summary>
|
|
public void UpdateCombo(int currentCombo)
|
|
{
|
|
Debug.Log($"[PerformanceManager] UpdateCombo called with: {currentCombo}");
|
|
CheckAchievementsByCategory(AchievementCategory.Combo, currentCombo);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 更新本局治疗总量并检查成就
|
|
/// </summary>
|
|
public void UpdateTotalCure(float totalCure)
|
|
{
|
|
Debug.Log($"[PerformanceManager] UpdateTotalCure called with: {totalCure}");
|
|
CheckAchievementsByCategory(AchievementCategory.TotalCure, totalCure);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 更新本局伤害总量并检查成就
|
|
/// </summary>
|
|
public void UpdateTotalDamage(float totalDamage)
|
|
{
|
|
Debug.Log($"[PerformanceManager] UpdateTotalDamage called with: {totalDamage}");
|
|
CheckAchievementsByCategory(AchievementCategory.TotalDamage, totalDamage);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 更新本局法力恢复总量并检查成就
|
|
/// </summary>
|
|
public void UpdateTotalManaRestored(float totalMana)
|
|
{
|
|
Debug.Log($"[PerformanceManager] UpdateTotalManaRestored called with: {totalMana}");
|
|
CheckAchievementsByCategory(AchievementCategory.TotalManaRestored, totalMana);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 通用的成就检测逻辑
|
|
/// </summary>
|
|
private void CheckAchievementsByCategory(AchievementCategory category, float currentValue)
|
|
{
|
|
if (achievementLibrary == null || achievementLibrary.Count == 0)
|
|
{
|
|
Debug.LogWarning($"[PerformanceManager] Achievement library is empty! Cannot check category: {category}");
|
|
return;
|
|
}
|
|
|
|
// 查找所有属于该逻辑分类的 SO 配置
|
|
var matchingCategories = achievementLibrary.Where(a => a.category == category).ToList();
|
|
|
|
if (matchingCategories.Count == 0)
|
|
{
|
|
Debug.LogWarning($"[PerformanceManager] No matching SO found for category: {category}. Library size: {achievementLibrary.Count}");
|
|
return;
|
|
}
|
|
|
|
foreach (var categorySO in matchingCategories)
|
|
{
|
|
// 找出该 SO 下满足条件的最高等级
|
|
AchievementLevel bestLevelForThisSO = categorySO.levels
|
|
.Where(l => currentValue >= l.triggerValue)
|
|
.OrderByDescending(l => l.triggerValue)
|
|
.FirstOrDefault();
|
|
|
|
if (bestLevelForThisSO != null)
|
|
{
|
|
// 检查该分类是否已经记录过成就
|
|
if (unlockedAchievements.TryGetValue(category, out var existingInfo))
|
|
{
|
|
// 如果当前 SO 达成的等级数值比已记录的更高,则更新
|
|
if (bestLevelForThisSO.triggerValue > existingInfo.level.triggerValue)
|
|
{
|
|
existingInfo.level = bestLevelForThisSO;
|
|
existingInfo.sourceSO = categorySO;
|
|
Debug.Log($"<color=green>[PerformanceManager] 分类 {category} 成就升级: {bestLevelForThisSO.levelName}</color>");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// 该分类第一次达成成就
|
|
unlockedAchievements.Add(category, new UnlockedAchievementInfo
|
|
{
|
|
level = bestLevelForThisSO,
|
|
sourceSO = categorySO
|
|
});
|
|
Debug.Log($"<color=cyan>[PerformanceManager] 分类 {category} 达成新成就: {bestLevelForThisSO.levelName}</color>");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 在结算界面实例化成就 UI
|
|
/// </summary>
|
|
public void LoadArchievePrefab()
|
|
{
|
|
if (archievePrefab == null)
|
|
{
|
|
Debug.LogWarning("[PerformanceManager] 无法实例化成就:通用预制体为空");
|
|
return;
|
|
}
|
|
|
|
// 1. 清空所有已配置的容器
|
|
if (place_to_putdown != null)
|
|
{
|
|
foreach (Transform child in place_to_putdown.transform) Destroy(child.gameObject);
|
|
}
|
|
foreach (var mapping in categoryDisplays)
|
|
{
|
|
if (mapping.parent != null)
|
|
{
|
|
foreach (Transform child in mapping.parent.transform) Destroy(child.gameObject);
|
|
}
|
|
}
|
|
|
|
// 2. 按稀有度排序并实例化
|
|
var sortedAchievements = unlockedAchievements.Values
|
|
.OrderByDescending(info => (int)info.level.rarity)
|
|
.ToList();
|
|
|
|
foreach (var info in sortedAchievements)
|
|
{
|
|
// 确定父物体:如果在映射表里找到了对应的 category,就用它的 parent;否则用默认的 place_to_putdown
|
|
GameObject targetParent = place_to_putdown;
|
|
|
|
// 注意:info.sourceSO 可能为空(防御性编程),所以先检查
|
|
AchievementCategory cat = info.sourceSO != null ? info.sourceSO.category : AchievementCategory.Combo;
|
|
|
|
var mapping = categoryDisplays.FirstOrDefault(m => m.category == cat);
|
|
if (mapping != null && mapping.parent != null)
|
|
{
|
|
targetParent = mapping.parent;
|
|
}
|
|
|
|
if (targetParent == null)
|
|
{
|
|
Debug.LogWarning($"[PerformanceManager] 分类 {cat} 没有可用的父容器 (默认容器也为空)");
|
|
continue;
|
|
}
|
|
|
|
// 实例化通用预制体
|
|
GameObject go = Instantiate(archievePrefab, targetParent.transform);
|
|
var script = go.GetComponent<archievePrefab>();
|
|
if (script != null)
|
|
{
|
|
script.Setup(info.level);
|
|
}
|
|
}
|
|
|
|
Debug.Log($"[PerformanceManager] 已在结算页面实例化 {sortedAchievements.Count} 个成就");
|
|
}
|
|
}
|