using System.Collections.Generic; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif public class uAchievementDisplayController : MonoBehaviour { [Header("prefabs")] public GameObject uAchievePrefab; public Transform contentParent; [Header("sprite list")] public Sprite[] achievementSprites; [Header("global achievement")] public bool initializeGlobalAchievementServiceOnEnable = true; public string runtimeResourcesPath = GlobalAchievementService.DefaultResourcesPath; public string editorAssetFolder = GlobalAchievementService.DefaultEditorAssetFolder; public List scannedGlobalAchievements = new List(); private void OnEnable() { if (initializeGlobalAchievementServiceOnEnable) { GlobalAchievementService.EnsureInstance().LoadDefinitionsFromResources(runtimeResourcesPath); } if (Application.isPlaying) { RefreshAchievementInstances(); } } #if UNITY_EDITOR private void OnValidate() { if (Application.isPlaying) { return; } ScanGlobalAchievementsInEditor(); } #endif public List GetGlobalAchievementSnapshots() { return GlobalAchievementService.EnsureInstance().GetSnapshots(); } private void Start() { if (Application.isPlaying) { RefreshAchievementInstances(); } } [ContextMenu("Scan Global Achievements")] public void ScanGlobalAchievements() { #if UNITY_EDITOR if (!Application.isPlaying) { ScanGlobalAchievementsInEditor(); return; } #endif scannedGlobalAchievements.Clear(); GlobalAchievementSO[] loaded = Resources.LoadAll(runtimeResourcesPath); if (loaded == null || loaded.Length == 0) { return; } scannedGlobalAchievements.AddRange(loaded); } public void RefreshAchievementInstances() { if (uAchievePrefab == null || contentParent == null) { return; } ClearAchievementInstances(); List snapshots = GetGlobalAchievementSnapshots(); List displaySnapshots = BuildHighestUnlockedSnapshotsPerSeries(snapshots); displaySnapshots.Sort(CompareSnapshots); for (int i = 0; i < displaySnapshots.Count; i++) { GlobalAchievementSnapshot snapshot = displaySnapshots[i]; if (!snapshot.unlocked || snapshot.definition == null) { continue; } GameObject instance = Instantiate(uAchievePrefab, contentParent); uAchievementPrefab controller = instance.GetComponent(); if (controller == null) { continue; } controller.Setup(snapshot, GetBottomSprite(snapshot.definition.achievementLevel)); } } private static List BuildHighestUnlockedSnapshotsPerSeries(List snapshots) { var result = new List(); var bestBySeries = new Dictionary(); for (int i = 0; i < snapshots.Count; i++) { GlobalAchievementSnapshot snapshot = snapshots[i]; if (!snapshot.unlocked || snapshot.definition == null) { continue; } string seriesKey = !string.IsNullOrWhiteSpace(snapshot.definition.achievementSeriesKey) ? snapshot.definition.achievementSeriesKey : snapshot.definition.metricType.ToString(); GlobalAchievementSnapshot currentBest; if (!bestBySeries.TryGetValue(seriesKey, out currentBest)) { bestBySeries[seriesKey] = snapshot; continue; } int levelCompare = snapshot.definition.achievementLevel.CompareTo(currentBest.definition.achievementLevel); if (levelCompare > 0) { bestBySeries[seriesKey] = snapshot; continue; } if (levelCompare == 0 && snapshot.unlockedUtc < currentBest.unlockedUtc) { bestBySeries[seriesKey] = snapshot; } } foreach (var pair in bestBySeries) { result.Add(pair.Value); } return result; } private void ClearAchievementInstances() { for (int i = contentParent.childCount - 1; i >= 0; i--) { Transform child = contentParent.GetChild(i); if (Application.isPlaying) { Destroy(child.gameObject); } else { DestroyImmediate(child.gameObject); } } } private Sprite GetBottomSprite(int level) { if (achievementSprites == null || achievementSprites.Length == 0) { return null; } int safeIndex = Mathf.Clamp(level, 0, achievementSprites.Length - 1); return achievementSprites[safeIndex]; } private static int CompareSnapshots(GlobalAchievementSnapshot left, GlobalAchievementSnapshot right) { int levelCompare = right.definition.achievementLevel.CompareTo(left.definition.achievementLevel); if (levelCompare != 0) { return levelCompare; } return left.unlockedUtc.CompareTo(right.unlockedUtc); } #if UNITY_EDITOR private void ScanGlobalAchievementsInEditor() { scannedGlobalAchievements.Clear(); if (string.IsNullOrWhiteSpace(editorAssetFolder)) { return; } string[] guids = AssetDatabase.FindAssets("t:GlobalAchievementSO", new[] { editorAssetFolder }); for (int i = 0; i < guids.Length; i++) { string assetPath = AssetDatabase.GUIDToAssetPath(guids[i]); GlobalAchievementSO definition = AssetDatabase.LoadAssetAtPath(assetPath); if (definition != null) { scannedGlobalAchievements.Add(definition); } } } #endif }