using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace GameFramework
{
///
/// 单条玩家得分记录。
///
[Serializable]
public class PlayerScore
{
public int score;
public string playerName;
public PlayerScore(int score, string playerName)
{
this.score = score;
this.playerName = playerName;
}
}
///
/// 可序列化的玩家得分列表(用于 JSON 存档)。
///
[Serializable]
public class PlayerScoreData
{
public List list = new List();
}
///
/// 得分管理器(持久单例)。
/// 维护当前局得分,通过事件通知 UI,并管理 Top-10 排行榜存档。
///
public class ScoreManager : PersistentSingleton
{
const int LEADERBOARD_SIZE = 10;
const string SAVE_FILE = "leaderboard.json";
// 当前局得分
int currentScore = 0;
// 当得分变化时触发,参数为最新得分(动画过程中的中间值也会触发)
public static event Action onScoreChanged;
// 当得分完成最终增加时触发,参数为最终得分
public static event Action onScoreSettled;
/// 当前得分(只读)。
public int CurrentScore => currentScore;
/// 默认玩家名,可在 Inspector 设置。
[SerializeField] string defaultPlayerName = "Player";
protected override void Awake()
{
base.Awake();
if (Instance != this) return;
currentScore = 0;
}
///
/// 增加得分(带数字滚动动画)。
///
public void AddScore(int amount)
{
if (amount <= 0) return;
StartCoroutine(ScoreCountUpCoroutine(currentScore, currentScore + amount));
}
///
/// 直接设置得分(无动画)。
///
public void SetScore(int value)
{
currentScore = Mathf.Max(0, value);
onScoreChanged?.Invoke(currentScore);
onScoreSettled?.Invoke(currentScore);
}
///
/// 重置当前局得分。
///
public void ResetScore()
{
currentScore = 0;
onScoreChanged?.Invoke(0);
onScoreSettled?.Invoke(0);
}
IEnumerator ScoreCountUpCoroutine(int from, int to)
{
currentScore = to;
float duration = 0.5f;
float elapsed = 0f;
while (elapsed < duration)
{
elapsed += Time.unscaledDeltaTime;
float t = Mathf.Clamp01(elapsed / duration);
int display = Mathf.RoundToInt(Mathf.Lerp(from, to, t));
onScoreChanged?.Invoke(display);
yield return null;
}
onScoreChanged?.Invoke(to);
onScoreSettled?.Invoke(to);
}
#region 排行榜
///
/// 当前得分是否能进入排行榜 Top-10。
///
public bool HasNewHighScore
{
get
{
var data = LoadPlayerScoreData();
if (data.list.Count < LEADERBOARD_SIZE)
return true;
return currentScore > data.list[LEADERBOARD_SIZE - 1].score;
}
}
///
/// 将当前得分以指定名字保存到排行榜。
/// 排行榜按分数降序排列,只保留 Top-10。
///
public void SavePlayerScore(string playerName)
{
if (string.IsNullOrEmpty(playerName))
playerName = defaultPlayerName;
var data = LoadPlayerScoreData();
data.list.Add(new PlayerScore(currentScore, playerName));
data.list.Sort((a, b) => b.score.CompareTo(a.score));
if (data.list.Count > LEADERBOARD_SIZE)
data.list.RemoveRange(LEADERBOARD_SIZE, data.list.Count - LEADERBOARD_SIZE);
SaveSystem.Save(SAVE_FILE, data);
}
///
/// 读取排行榜数据。
///
public PlayerScoreData LoadPlayerScoreData()
{
if (SaveSystem.SaveFileExists(SAVE_FILE))
return SaveSystem.Load(SAVE_FILE);
return new PlayerScoreData();
}
///
/// 清空排行榜存档。
///
public void ClearLeaderboard()
{
SaveSystem.DeleteSaveFile(SAVE_FILE);
}
#endregion
}
}