基本流程
时间系统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);elseclockBlocks[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是一个动画插件,可以了解一下