| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578 |
- using UnityEngine;
- using UnityEngine.UI;
- using System.Collections.Generic;
- using System.Collections;
- using UnityEngine.Networking;
- using Newtonsoft.Json.Linq;
- using System;
- namespace LocalRank
- {
- [RequireComponent(typeof(RankUpAnimator))]
- public class RankManager : MonoBehaviour
- {
- public Transform Panel; //是否显示
- public Transform content; // Content节点
- public GameObject itemPrefab; // 排行榜Item预制体
- public InputField inputField;
- private RankUpAnimator rankUpAnimator; // RankUpAnimator脚本引用
- private List<RankItemData> rankDataList = new List<RankItemData>();
- /// <summary>
- /// 当前的排名分数
- /// </summary>
- public static int CurrentScore = 0;
- /// <summary>
- /// 维护一个全局的userId
- /// </summary>
- public static int userId { get; private set; }
- /// <summary>
- /// 是否创建userId
- /// </summary>
- private static bool userIdCreated = false;
- public static bool HasUserId => userIdCreated;
- /// <summary>
- /// 是否在滚动
- /// </summary>
- private bool isRuning = false;
- //退出
- public Action OnBackClicked;
- // 你可以在这里定义游戏 ID 或者动态获取
- private int gameId = 1;
- /// <summary>
- /// 创建一个排行榜
- /// </summary>
- /// <param name="gameType"></param>
- public static void CreateRankView(int gameType,Action callback) {
- Debug.Log("当前上传的本地排行榜ID:"+ gameType);
- //b端时候处理一个结束排行榜
- GameObject rankObj = ViewManager2.getGameObjectAndShowView(ViewManager2.Path_GameRankView);
- RankManager gameRankView = rankObj.GetComponent<RankManager>();
- gameRankView.OnBackClicked += ()=> {
- ViewManager2.HideView(ViewManager2.Path_GameRankView);
- callback?.Invoke();
- };
- gameRankView.CreateRankGameInfo(gameType);
- gameRankView.UploadCurrentScoreToNewId();
- }
- private void Awake()
- {
- rankUpAnimator = GetComponent<RankUpAnimator>();
- if (rankUpAnimator == null)
- {
- Debug.LogError("RankUpAnimator 组件未找到!");
- }
- if (inputField != null)
- {
- inputField.onEndEdit.AddListener(InputScore);
- }
- }
- private void Start()
- {
- rankUpAnimator.onAnimationStart = () =>
- {
- isRuning = true;
- HideAllRankIcons(); // 滚动前隐藏图标和名次数字
- };
- rankUpAnimator.onAnimationComplete = () =>
- {
- isRuning = false;
- RefreshRankIcons(); // 滚动后恢复图标或数字
- };
- //CreateRankGameInfo();
- //CreateUserId();
- }
- /// <summary>
- /// 设置分数。用于后续上传排行榜显示
- /// </summary>
- /// <param name="score"></param>
- public static void SetCurrentScore(int score = 0) {
- if (score > 0) {
- CurrentScore = score;
- }
- }
-
- /// <summary>
- /// 创建本地排行榜,进入场景时候直接创建。比如游戏场景
- /// 不同的游戏ID对应不同的排行榜
- /// </summary>
- public void CreateRankGameInfo(int CurrentGameId = 1)
- {
- gameId = CurrentGameId;
- // 判断是否已创建表
- if (RankService.IsTableExists(gameId))
- {
- Debug.Log($"rank_game_{gameId} 表已存在!");
- }
- else
- {
- Debug.Log($"rank_game_{gameId} 表不存在,正在创建...");
- RankService.CreateTableIfNotExists(gameId);
- }
- }
- /// <summary>
- /// 如果需要维护一个常用id的话
- /// 调用这里创建userId,每个userId都是单独记录排行榜数据。
- /// </summary>
- public void CreateUserId()
- {
- //获取一个时间戳值
- userId = RankService.GenerateLocalUserId();
- //记录一个标识
- userIdCreated = true;
- }
-
- /// <summary>
- /// 直接上传分数到当前用户信息
- /// </summary>
- public void UploadCurrentScoreToUserId()
- {
- if (!HasUserId)
- {
- Debug.LogError("无效的本地用户id!");
- return;
- }
- if (CurrentScore != 0)
- {
- if (isRuning)
- {
- Debug.LogError("操作频繁!等排行榜停止在操作!");
- return;
- }
- RankService.UploadScore(gameId, userId, "Player_" + userId, "", CurrentScore);
- Debug.Log($"UploadScoreToUserId rank_game_{gameId} 上传 Id:{userId}分数:{CurrentScore}!");
- GetLocalRankList();
- CurrentScore = 0;
- }
- }
-
- /// <summary>
- /// 上传当前操作分数到新用户
- /// </summary>
- public void UploadCurrentScoreToNewId() {
- if (CurrentScore != 0)
- {
- if (isRuning)
- {
- Debug.LogError("操作频繁!等排行榜停止在操作!");
- return;
- }
- Panel.gameObject.SetActive(true);
- UploadNewIdScore(CurrentScore);
- CurrentScore = 0;
- }
- else
- {
- //分数是0直接进行下一步
- OnBackClicked?.Invoke();
- }
- }
- /// <summary>
- /// 直接上传一个新用户id分数
- /// </summary>
- private void UploadNewIdScore(int score = 0)
- {
- int newUserId = RankService.GenerateLocalUserId();
- RankService.UploadScore(gameId, newUserId, "Player_" + newUserId, "", score);
- Debug.Log($"UploadNewIdScore rank_game_{gameId} 上传 新Id:{newUserId}分数:{score}!");
- //更新当前用户信息
- userId = newUserId;
- userIdCreated = true;
- GetLocalRankList();
- }
- #region 测试数据操作
- /// <summary>
- /// 通过Input End 上传分数
- /// </summary>
- /// <param name="score"></param>
- void InputScore(string score)
- {
- if (!HasUserId)
- {
- Debug.LogError("无效的本地用户id!");
- return;
- }
- int parsedScore;
- if (!int.TryParse(score, out parsedScore))
- {
- Debug.LogError("输入的分数无效!");
- return;
- }
- if (isRuning)
- {
- Debug.LogError("操作频繁!等排行榜停止在操作!");
- return;
- }
- RankService.UploadScore(gameId, userId, "Player_" + userId, "", parsedScore);
- Debug.Log($"InputScore rank_game_{gameId} 上传 Id:{userId}分数:{parsedScore}");
- GetLocalRankList();
- }
- /// <summary>
- /// 上传测试分数
- /// </summary>
- /// <param name="score"></param>
- public void UploadTestRandomScoreToUserId()
- {
- if (!HasUserId)
- {
- Debug.LogError("无效的本地用户id!");
- return;
- }
- if (isRuning)
- {
- Debug.LogError("操作频繁!等排行榜停止在操作!");
- return;
- }
- int seed = 0;
- var random = seed == 0 ? new System.Random() : new System.Random(seed);
- int _score = random.Next(0, 1000); // 随机的分数 0~999 分之间
- RankService.UploadScore(gameId, userId, "Player_" + userId, "", _score);
- Debug.Log($"UploadTestRandomScoreToUserId rank_game_{gameId} 上传 Id:{userId}分数:{_score}!");
- GetLocalRankList();
- }
- /// <summary>
- /// 上传随机分数到新用户
- /// </summary>
- public void UploadTestRandomScoreToNewId()
- {
- if (isRuning)
- {
- Debug.LogError("操作频繁!等排行榜停止在操作!");
- return;
- }
- int seed = 0;
- var random = seed == 0 ? new System.Random() : new System.Random(seed);
- int _score = random.Next(1, 1000); // 随机的分数是 1~999 分之间
- UploadNewIdScore(_score);
- }
- /// <summary>
- /// 测试数据调用
- /// </summary>
- public void TestData()
- {
- InsertTestData();
- }
- /// <summary>
- /// 按钮调用,重新填充排行榜数据
- /// </summary>
- // public void AnimatorRunButton()
- // {
- // PopulateRankList(true); // 重新填充排行榜数据
- // }
- /// <summary>
- /// 插入测试数据
- /// </summary>
- /// <param name="seed"></param>
- private void InsertTestData(int seed = 0)
- {
- var random = seed == 0 ? new System.Random() : new System.Random(seed);
- for (int i = 1; i <= 20; i++)
- {
- int userId = 1000 + i;
- string nickname = $"玩家{i:D2}";
- string avatarUrl = ""; // 可以填测试图片链接或留空
- int score = random.Next(0, 10000); // 0~9999 分之间
- RankService.UploadScore(gameId, userId, nickname, avatarUrl, score);
- }
- Debug.Log($"已为 gameId={gameId} 插入 20 条测试数据");
- }
- #endregion
- /// <summary>
- /// 获取本地排行榜
- /// </summary>
- void GetLocalRankList()
- {
- if (!HasUserId)
- {
- Debug.LogError("先创建用户id再获取排行榜!");
- return;
- }
- rankDataList.Clear();
- RankItemData selfItem = null;
- const int MaxRankDisplayCount = 9; // 展示排行榜上限,最后一位预留给自己
- int maxRank = 0;//记录最大的max
- int index = 0;//当前下标
- var (ranks, selfRank, total) = RankService.GetRankList(gameId: gameId, userId: userId);
- foreach (var r in ranks)
- {
- // Debug.Log($"[{r.Rank}] {r.Nickname} - {r.Score} {(r.IsSelf ? "(你)" : "")}");
- var data = new RankItemData
- {
- Rank = r.Rank,
- UserName = r.Nickname,
- Score = r.Score,
- AvatarUrl = r.AvatarUrl,
- IsSelf = r.IsSelf,
- RankIndex = index++
- };
- // Debug.Log($"成功解析data {data} 排行榜数据");
- if (data.IsSelf)
- selfItem = data;
- else
- rankDataList.Add(data);
- maxRank = Mathf.Max(maxRank, r.Rank);//记录最大值
- }
- //Debug.Log($"成功解析 {rankDataList.Count} 条排行榜数据");
- // 如果总数量不足 MaxRankDisplayCount,补充假数据
- int currentCount = rankDataList.Count;
- int otherIndex = 0;
- for (int i = currentCount; i < MaxRankDisplayCount; i++)
- {
- ++otherIndex;
- var fakeData = new RankItemData
- {
- Rank = maxRank + otherIndex,
- UserName = $"游客玩家 {i + 1}",
- Score = 0,
- AvatarUrl = "", // 可替换为默认头像路径
- IsSelf = false,
- RankIndex = index++
- };
- rankDataList.Add(fakeData);
- }
- // 最后添加自己(先放在最后一位)
- if (selfItem != null)
- {
- rankDataList.Add(selfItem);
- }
- // Debug.Log($"最终排行榜数据条数: {rankDataList.Count}");
- PopulateRankList(true);
- }
- /// <summary>
- /// 获取远程排行榜数据
- /// 暂时不使用
- /// </summary>
- /// <returns></returns>
- private IEnumerator FetchRankDataFromServer()
- {
- string url = "http://192.168.0.108:11432/SmartBowBusinessServer/SmartBowSDK/UploadScoreAndGetSeasonCenterRankList" +
- "?token=3421-1746758375311-5786b88c34343d142bea1dd31a1cb315" +
- "&rankArea=2&rankGameType=1001&score=9937" +
- "&countryCode=中国&stateCode=广东省&cityCode=清远市";
- UnityWebRequest request = UnityWebRequest.Post(url, "");
- yield return request.SendWebRequest();
- if (request.result != UnityWebRequest.Result.Success)
- {
- Debug.LogError("Request Failed: " + request.error);
- yield break;
- }
- string json = request.downloadHandler.text;
- ParseRankJson(json);
- }
- /// <summary>
- /// 解析远程排行榜数据
- /// </summary>
- /// <param name="json"></param>
- private void ParseRankJson(string json)
- {
- rankDataList.Clear();
- JObject root = JObject.Parse(json);
- JArray rankArray = (JArray)root["data"][0];
- RankItemData selfItem = null;
- int index = 0;
- foreach (JObject item in rankArray)
- {
- var data = new RankItemData
- {
- Rank = item["rankNum"] != null ? (int)item["rankNum"] : 0,
- UserName = item["nickname"]?.ToString() ?? "Unknown",
- Score = item["score"] != null ? (int)item["score"] : 0,
- AvatarUrl = item["avatarUrl"]?.ToString() ?? "",
- IsSelf = item["isSelf"]?.ToObject<bool>() ?? false,
- RankIndex = index++
- };
- Debug.Log($"成功解析data {data} 排行榜数据");
- if (data.IsSelf)
- selfItem = data;
- else
- rankDataList.Add(data);
- }
- // 最后添加自己(先放在最后一位)
- if (selfItem != null)
- {
- rankDataList.Add(selfItem);
- }
- Debug.Log($"成功解析 {rankDataList.Count} 条排行榜数据");
- PopulateRankList();
- }
- /// <summary>
- /// 开始跑循环分数时候调用
- /// </summary>
- public void HideAllRankIcons()
- {
- for (int i = 0; i < content.childCount; i++)
- {
- var item = content.GetChild(i);
- var itemUI = item.GetComponent<RankItemUI>();
- if (itemUI != null)
- {
- //itemUI.HideIconAndText();
- itemUI.StartRunUI();
- }
- }
- }
- /// <summary>
- /// 结束循环分数时候调用
- /// </summary>
- public void RefreshRankIcons()
- {
- for (int i = 0; i < content.childCount; i++)
- {
- var item = content.GetChild(i);
- var itemUI = item.GetComponent<RankItemUI>();
- if (itemUI != null)
- {
- itemUI.StopRunUI();
- }
- }
- }
- /// <summary>
- /// 填充排行榜列表,生成排行榜预制item
- /// </summary>
- /// <param name="isStartup"></param>
- private void PopulateRankList(bool isStartup = false)
- {
- foreach (Transform child in content)
- Destroy(child.gameObject);
- for (int i = 0; i < rankDataList.Count; i++)
- {
- var data = rankDataList[i];
- GameObject itemObj = Instantiate(itemPrefab, content);
- itemObj.name = $"RankItem_{data.Rank}";
- RankItemUI itemUI = itemObj.GetComponent<RankItemUI>();
- if (itemUI != null)
- {
- itemUI.SetData(data);
- if (!string.IsNullOrEmpty(data.AvatarUrl))
- StartCoroutine(LoadAvatarImage(data.AvatarUrl, itemUI.avatarImage));
- }
- else
- {
- Debug.LogWarning("预制体上缺少 RankItemUI 脚本");
- }
- }
- if (isStartup)
- StartCoroutine(DelayedStartAnimation());
- }
- /// <summary>
- /// 加载头像图片
- /// </summary>
- /// <param name="url"></param>
- /// <param name="targetImage"></param>
- /// <returns></returns>
- private IEnumerator LoadAvatarImage(string url, Image targetImage)
- {
- UnityWebRequest request = UnityWebRequestTexture.GetTexture(url);
- yield return request.SendWebRequest();
- if (request.result != UnityWebRequest.Result.Success)
- {
- Debug.LogWarning("头像加载失败: " + request.error);
- yield break;
- }
- Texture2D texture = DownloadHandlerTexture.GetContent(request);
- Sprite avatarSprite = Sprite.Create(texture,
- new Rect(0, 0, texture.width, texture.height),
- new Vector2(0.5f, 0.5f));
- targetImage.sprite = avatarSprite;
- }
- /// <summary>
- /// 延迟开始动画
- /// </summary>
- /// <returns></returns>
- IEnumerator DelayedStartAnimation()
- {
- yield return null;
- // TestRankUpFromTo(10, 1);
- //查找“自己”的索引和目标真实排名索引
- int startIndex = rankDataList.Count;
- RankItemData selfData = rankDataList.Find(d => d.IsSelf);
- int targetIndex = selfData.RankIndex + 1; // 目标名次是自己在列表中的索引 + 1
- // for (int i = 0; i < rankDataList.Count; i++)
- // {
- // var data = rankDataList[i];
- // Debug.Log($"[{data.Rank}] {data.UserName} - {data.Score} {(data.IsSelf ? "(你)" : "")} ,RankIndex: {data.RankIndex}");
- // }
- // Debug.Log($"startIndex:{startIndex} targetIndex:{targetIndex}");
- if (startIndex != targetIndex)
- {
- RankUpFromTo(startIndex, targetIndex);
- }
- }
- /// <summary>
- /// 测试冲榜动画:从 startIndex 冲到 targetRankIndex
- /// </summary>
- void RankUpFromTo(int startIndex, int targetRankIndex)
- {
- if (startIndex <= 0 || startIndex > content.childCount)
- {
- Debug.LogError("无效的起始排名!");
- return;
- }
- if (targetRankIndex <= 0 || targetRankIndex > content.childCount)
- {
- Debug.LogError("无效的目标排名!");
- return;
- }
- // 获取起始 item
- Transform startItem = content.GetChild(startIndex - 1);
- // 设置 animator 的目标元素和目标名次
- rankUpAnimator.targetItem = startItem.GetComponent<RectTransform>();
- rankUpAnimator.targetRankIndex = targetRankIndex;
- // 调用冲榜动画
- rankUpAnimator.StartRankUpAnimation(startIndex, targetRankIndex);
- }
- public void OnClick_Back()
- {
- if (isRuning) return;
- //AudioMgr.ins.PlayBtn();
- OnBackClicked?.Invoke();
- }
- }
- }
|