麦田物语学习笔记:代码链接UI实现时间日期对应转换
基本流程
时间系统UI如下
本篇文章将UI和TimeManager里的数据联系在一起,
1.代码思路
(1)新建TimeUI.cs挂载在GameTime物体上,然后获取它的子物体这些组件来改变里面的数值,所以需要获得Day & Night的子物体Image中的Rect Transform,用于旋转季节的图标;获得Clock每个子物体的显示;以及日期,时间,季节的图片的显示
图中围绕季节一周的是时间的区块显示,每4个小时会增加一格
(2)像日夜交换,时间的区块显示,季节变换,日期显示都和小时有关;只有具体时间的文本显示与秒有关,所以需要创建两个事件,这两个事件帮助我们呼叫,告诉UI切换数据.然后在TimeManager相应位置呼叫事件,最后在TimeUI当中注册这些事件
这里当然可以只用一个事件,但是由于与秒相关的事件调用频繁,所以考虑到性能开销,这里用了两个事件呼叫
(3)需要注意的是,要将时间更新的代码在一开始就执行
2.代码实现
新增TimeManager中的代码
private void Start()
{
EventHandler.CallGameDataEvent(gameHour, gameDay, gameMonth, gameYear, gameSeason);
EventHandler.CallGameMinuteEvent(gameMinute, gameHour);
}
private void UpdateGameTime()
{
gameSecond++;
if (gameSecond > Settings.secondHold)
{
gameMinute++;
gameSecond = 0;
if (gameMinute > Settings.minuteHold)
{
gameHour++;
gameMinute = 0;
if (gameHour > Settings.hourHold)
{
gameDay++;
gameHour = 0;
if (gameDay > Settings.dayHold)
{
gameMonth++;
gameDay = 1;
if (gameMonth > 12)
{
gameMonth = 1;
}
monthInSeason--;
if (monthInSeason == 0)
{
monthInSeason = 3;
int seasonNumber = (int)gameSeason;
seasonNumber++;
if (seasonNumber > Settings.seasonHold)
{
gameYear++;
seasonNumber = 0;
}
gameSeason = (Season)seasonNumber;
if (gameYear > 9999)
{
gameYear = 2025;
}
}
}
}
EventHandler.CallGameDataEvent(gameHour, gameDay, gameMonth, gameYear, gameSeason);
}
EventHandler.CallGameMinuteEvent(gameMinute, gameHour);
}
//Debug.Log("Second: " + gameSecond + "Minte: " + gameMinute);
}
新增两个事件
//跟分钟相关
public static event Action<int, int> GameMinuteEvent;
public static void CallGameMinuteEvent(int minute,int hour)
{
GameMinuteEvent?.Invoke(minute,hour);
}
//跟日期相关
public static event Action<int,int,int,int,Season> GameDataEvent;
public static void CallGameDataEvent(int hour,int day,int month,int year,Season season)
{
GameDataEvent?.Invoke(hour,day,month,year,season);
}
TimeUI.cs
public class TimeUI : MonoBehaviour
{
public RectTransform dayNightImage;
public RectTransform clockParent;
public TextMeshProUGUI dataText;
public TextMeshProUGUI timeText;
public Image seasonImage;
public Sprite[] seasonSprites;//获取四个季节的图片
public List<GameObject> clockBlocks = new List<GameObject>();//获取代表时间的各个物体
private void Awake()
{
for (int i = 0;i < clockParent.childCount;i++)
{
clockBlocks.Add(clockParent.GetChild(i).gameObject);
clockParent.GetChild(i).gameObject.SetActive(false);
}
}
private void OnEnable()
{
EventHandler.GameMinuteEvent += OnGameMinuteEvent;
EventHandler.GameDataEvent += OnGameDataEvent;
}
private void OnDisable()
{
EventHandler.GameMinuteEvent -= OnGameMinuteEvent;
EventHandler.GameDataEvent -= OnGameDataEvent;
}
private void OnGameMinuteEvent(int minute, int hour)
{
//TimeText有关的
timeText.text = hour.ToString("00") + ":" + minute.ToString("00"); //这里的"00"是用来规定格式的,不是赋值
}
private void OnGameDataEvent(int hour, int day, int month, int year, Season season)
{
//日期相关
dataText.text = year + "年" + month.ToString("00") + "月" + day.ToString() + "日";
seasonImage.sprite = seasonSprites[(int)season];
SwitchHourImage(hour);
DayNightImageRotate(hour);
}
/// <summary>
/// 根据时间显示区块
/// </summary>
/// <param name="hour"></param>
private void SwitchHourImage(int hour)
{
int index = hour / 4;
//先考虑0的情况:把所有时间块全部关闭
if (index == 0)
{
foreach (var item in clockBlocks)
{
item.SetActive(false);
}
}
else
{
for (int i = 0; i < clockBlocks.Count;i++)
{
if(i < index + 1)
clockBlocks[i].SetActive(true);
else
clockBlocks[i].SetActive(false);
}
}
}
private void DayNightImageRotate(int hour)
{
var target = new Vector3(0,0,hour * 15 - 90);
dayNightImage.DORotate(target, 1f, RotateMode.Fast);
}
}
最终效果
根据时间旋转相应的图片显示以及区块显示
0点时清空区块
补充知识点
1.DoTween
DOTween是一个动画插件,可以了解一下