泛型能解决一些重复性的问题,比如分数从大到小排,死亡数从大到小排等等
这里先封装玩家数据
如名字,击杀数,死亡数等
using UnityEngine;
[System.Serializable]
public class PlayerStatus
{
public string playerName;
public int killNmber, deatNmber, flagNmber;
public Sprite profileSprite, playerSprite;
[HideInInspector] public string title;
[HideInInspector] public string dateTime;
public static bool CompareKill(PlayerStatus playerStatusA, PlayerStatus playerStatusB) => playerStatusA.killNmber>playerStatusB.killNmber;
}
再创建一个游戏数据处理类,单列模式,来计算玩家的数据的排序
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
/// <summary>
/// 委托条件 参数要一致至 返回值也有一致
/// Action 可以带参数 没有返回值
/// Func 可以带参数 有返回值
/// </summary>
public class GameDataManager : MonoBehaviour
{
public static GameDataManager Instance;
public PlayerStatus[] playstatus;
[HideInInspector] public string topSkllName, topDeathName, topFlagName;//[HideInInspector] Inspector隐藏 不能在unity中看到和编辑
private void Awake()
{
if(Instance!=null)
{
Destroy(Instance);
}
else
{
Instance= this;
}
DontDestroyOnLoad(Instance);
}
private void Start()
{
topSkllName=GetTopNum((player) => player.killNmber);
topDeathName=GetTopNum((player) => player.deatNmber);
topFlagName=GetTopNum((player) => player.flagNmber);
UIManager.Instance.UpdatePlayerTitle(topSkllName, "杀人王", (player) => player.playerName);
UIManager.Instance.UpdatePlayerTitle(topDeathName, "死亡者", Logger.Log);
UIManager.Instance.UpdatePlayerTitle(topFlagName, "夺标晓", Logger.Log);
Debug.Log("kill "+GetTopNum((player) => player.killNmber));//lambda 会做类型推断 等同与上方的 //public int GetPlayerKillNum(PlayerStatus player)
Debug.Log("death"+GetTopNum((player) => player.deatNmber));
Debug.Log("flag"+GetTopNum((player) => player.flagNmber));
UIManager.Instance.UpdataLeftUI();
UIManager.Instance.UpdataRightUI();
UIManager.Instance.UpdateSoltAlpha();
}
//委托 找到最大值
public string GetTopNum(Func<PlayerStatus,int> func)//PlayerStatus 是参数 int 返回值
{
string topName = "";
int bestRecrod = 0;
foreach(PlayerStatus player in playstatus)
{
int tempNum = func(player);
if(tempNum>bestRecrod)
{
bestRecrod = tempNum;
topName=player.playerName;
}
}
return topName;
}
//委托 冒泡排序法 泛型
public void BubbleSort<T>(T[] playerStatuses ,Func<T, T, bool> func)
{
bool isSwapped=false;
do
{
isSwapped=false;
for (int i = 0; i <playerStatuses.Length-1; i++)
{
if (func(playerStatuses[i], playerStatuses[i+1]))
{
T temp = playerStatuses[i];
playerStatuses[i]= playerStatuses[i+1];
playerStatuses[i+1]= temp;
isSwapped=true;
}
}
}while( isSwapped);
UIManager.Instance.UpdataLeftUI();
}
}
在创建一个UI管理类负责UI的显示
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.UI;
public class UIManager : MonoBehaviour
{
public static UIManager Instance;
int currentIndex;
[Header("left UI")]
public GameObject[] solts;
[Header("right UI")]
public Text statauText;
public Image playerImage;
public Text playerName;
public Text titleText;//ToDo 称号
[Header("按钮")]
public Button leftButton, rightButton, skllButton, deatButton, flagButton;
bool isAscendSkll=true;//判断是否倒序 从底层 从小到大
bool isAscendDeath=true;//判断是否倒序
bool isAscendFlag=true;//判断是否倒序
bool isPressButton = true;
private void Awake()
{
if (Instance!=null)
{
Destroy(Instance);
}
else
{
Instance= this;
}
DontDestroyOnLoad(Instance);
}
private void Start()
{
leftButton.onClick.AddListener(BackButton);
rightButton.onClick.AddListener(NextButton);
skllButton.onClick.AddListener(KillSortButton);
deatButton.onClick.AddListener(DeathSortButton);
flagButton.onClick.AddListener(FlagSortButton);
// skllButton.onClick.AddListener(() => SortMetond(GameDataManager.Instance.playstatus, (playerStatusA, playerStatusB) => playerStatusA.killNmber>playerStatusB.killNmber));
}
private void Update()
{
Debug.Log(isPressButton);
}
//更新左边UI
public void UpdataLeftUI()
{
for (int i = 0; i < solts.Length; i++)
{
solts[i].transform.GetChild(0).GetComponent<Image>().sprite=GameDataManager.Instance.playstatus[i].profileSprite;
solts[i].GetComponentInChildren<Text>().text=string.Format("{0}/{1}/{2}", GameDataManager.Instance.playstatus[i].killNmber,
GameDataManager.Instance.playstatus[i].deatNmber,
GameDataManager.Instance.playstatus[i].flagNmber);
solts[i].transform.GetChild(2).GetComponent<Text>().text=GameDataManager.Instance.playstatus[i].dateTime;
Debug.Log(i+"号"+GameDataManager.Instance.playstatus[i].dateTime);
}
}
//图层透明度控制
public void UpdateSoltAlpha()
{
for (int i = 0; i < solts.Length; i++)
{
if(i==currentIndex)
{
solts[i].GetComponent<CanvasGroup>().alpha=1f;
solts[i].transform.GetChild(0).GetComponentInChildren<ParticleSystem>().Play();//获得子物体的粒子
}
else
{
// solts[i].GetComponent<CanvasGroup>().alpha=0.25f;
UITweener.instance.AlphaChange(solts[i].GetComponent<CanvasGroup>(), 0.25f);
solts[i].transform.GetChild(0).GetComponentInChildren<ParticleSystem>().Stop();//获得子物体的粒子
}
}
}
//更新右边UI
public void UpdataRightUI()
{
PlayerStatus playerStatus = GameDataManager.Instance.playstatus[currentIndex];
playerImage.sprite=playerStatus.playerSprite;
statauText.text=string.Format("{0}/{1}/{2}", playerStatus.killNmber, playerStatus.deatNmber, playerStatus.flagNmber);
playerName.text=playerStatus.playerName;
titleText.text=playerStatus.title;
}
//更新玩家称号
public void UpdatePlayerTitle(string topName,string title,Func<PlayerStatus,string> func)
{
for (int i = 0; i < GameDataManager.Instance.playstatus.Length; i++)//遍历数据
{
if (GameDataManager.Instance.playstatus[i].playerName==topName)
{
GameDataManager.Instance.playstatus[i].title=title;
GameDataManager.Instance.playstatus[i].dateTime=func(GameDataManager.Instance.playstatus[i]);
}
}
}
//总排列方法 <T> 泛型标志
public void SortMetond<T>(T[] playerStatuses, Func<T, T, bool> func,bool isAscend)
{
if (isAscend)//是否升序
{
GameDataManager.Instance.BubbleSort(playerStatuses, func);
}
else
{
ReverseArray();
}
UpdataLeftUI();
UpdataRightUI();
UpdateSoltAlpha();
}
//右按钮
public void NextButton()
{
if(isPressButton)
{
currentIndex++;
if (currentIndex >= solts.Length)
{
currentIndex=0;
}
UpdataRightUI();
UpdateSoltAlpha();
UIAimitor();
}
StopCoroutine(nameof(PressButtonCorotinue));
StartCoroutine(nameof(PressButtonCorotinue));
}
//左按钮
public void BackButton()
{
if (isPressButton)
{
currentIndex--;
if (currentIndex<0)
{
currentIndex=solts.Length-1;
}
UpdataRightUI();
UpdateSoltAlpha();
UIAimitor();
}
StopCoroutine(nameof(PressButtonCorotinue));
StartCoroutine(nameof(PressButtonCorotinue));
}
//击杀数排列
public void KillSortButton()
{
SortMetond(GameDataManager.Instance.playstatus,(playerStatusA, playerStatusB) => playerStatusA.killNmber>playerStatusB.killNmber,isAscendSkll);
isAscendSkll=!isAscendSkll;
isAscendDeath=true;
isAscendFlag=true;
}
//死亡数排列
public void DeathSortButton()
{
SortMetond(GameDataManager.Instance.playstatus, (playerStatusA, playerStatusB) => playerStatusA.deatNmber>playerStatusB.deatNmber,isAscendDeath);
isAscendDeath=!isAscendDeath;
isAscendFlag=true;
isAscendSkll=true;
}
//旗帜排列
public void FlagSortButton()
{
SortMetond(GameDataManager.Instance.playstatus, (playerStatusA, playerStatusB) => playerStatusA.flagNmber>playerStatusB.flagNmber,isAscendFlag);
isAscendFlag=!isAscendFlag;
isAscendDeath=true;
isAscendSkll=true;
}
//将数组倒序
public void ReverseArray()=>Array.Reverse(GameDataManager.Instance.playstatus);
//各种ui动画效果
public void UIAimitor()
{
UITweener.instance.DoTweenPlayerImage();
}
IEnumerator PressButtonCorotinue()//IEnumerator 开始协程
{
isPressButton=false;
yield return new WaitForSeconds(0.5f);
isPressButton=true;
}
}
显示获得称呼的时间
using UnityEngine;
using System;
public class Logger
{
public static string Log(PlayerStatus player)
{
DateTime currentTime= DateTime.UtcNow;//通用时间 UtcNow不带时区
Debug.Log(string.Format("{0}{1}{2}", player.playerName, player.title, player.dateTime));
return currentTime.ToString();
}
}
后面可以用Dotween来丰富UI的交互
using UnityEngine;
using DG.Tweening;
using UnityEngine.EventSystems;
public class UITweener : MonoBehaviour
{
public static UITweener instance;
public RectTransform statusRT, playerImageRT, playerTextRT, titleTextRT;
public RectTransform nextButton, backButton;
private void Awake()
{
if (instance == null)
{
instance = this;
}
else
{
if (instance != null)
{
Destroy(gameObject);
}
}
DontDestroyOnLoad(gameObject);
}
//鼠标进入【上下页按钮】触发,按钮变大
public void ScaleIn(RectTransform _trans)
{
_trans.DOScale(new Vector3(2f, 2f, 2f), 0.2f).SetEase(Ease.InSine);
}
//鼠标离开【上下页按钮】触发,按钮恢复
public void ScaleOut(RectTransform _trans)
{
_trans.DOScale(new Vector3(1f, 1f, 1f), 0.2f).SetEase(Ease.OutSine);
}
//鼠标点击【上下页按钮】触发,右侧人物“扭动”动画
public void ShakeScale(RectTransform _trans)
{
_trans.DOShakeScale(0.5f, 0.25f, 10, 15);
}
//鼠标点击【上下页按钮】触发,右侧人物信息“颤抖”动画
public void ShakeRotation(RectTransform _trans)
{
_trans.DOShakeRotation(0.5f, 25, 5, 25);
}
//改变透明度
public void AlphaChange(CanvasGroup _canvasGroup, float _amount)
{
_canvasGroup.DOFade(_amount, 0.5f);//DOFade 透明度 所需时间
}
public void DoTweenPlayerImage()
{
ShakeScale(playerImageRT);
ShakeRotation(statusRT);
ShakeScale(playerTextRT);
ShakeRotation(titleTextRT);
}
}
详细的可以学习
【UI游戏界面】上下页切换,委托类型作为方法的参数和LAMBDA表达式的实际使用(附:计算所有数据最高的方法,GetChild方法优缺点等)_哔哩哔哩_bilibili