218 lines
6.3 KiB
C#
218 lines
6.3 KiB
C#
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<GlobalAchievementSO> scannedGlobalAchievements = new List<GlobalAchievementSO>();
|
|
|
|
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<GlobalAchievementSnapshot> 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<GlobalAchievementSO>(runtimeResourcesPath);
|
|
if (loaded == null || loaded.Length == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
scannedGlobalAchievements.AddRange(loaded);
|
|
}
|
|
|
|
public void RefreshAchievementInstances()
|
|
{
|
|
if (uAchievePrefab == null || contentParent == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ClearAchievementInstances();
|
|
|
|
List<GlobalAchievementSnapshot> snapshots = GetGlobalAchievementSnapshots();
|
|
List<GlobalAchievementSnapshot> 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<uAchievementPrefab>();
|
|
if (controller == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
controller.Setup(snapshot, GetBottomSprite(snapshot.definition.achievementLevel));
|
|
}
|
|
}
|
|
|
|
private static List<GlobalAchievementSnapshot> BuildHighestUnlockedSnapshotsPerSeries(List<GlobalAchievementSnapshot> snapshots)
|
|
{
|
|
var result = new List<GlobalAchievementSnapshot>();
|
|
var bestBySeries = new Dictionary<string, GlobalAchievementSnapshot>();
|
|
|
|
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<GlobalAchievementSO>(assetPath);
|
|
if (definition != null)
|
|
{
|
|
scannedGlobalAchievements.Add(definition);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|