用途
通过TimeSys生成1个Timer。
生成时,可设置是否立即开始计时、该计时器是否忽略Time.timeScale变化的影响
对于单个计时器,可以:开始计时、暂停计时、继续计时、重置时间。
UnityTime相关的小知识
- FixedUpdate()的执行频率会受Time.timeScale的影响,当scale=0时不执行。
- Update和LateUpdate不受Time.timeScale的影响。
- Time.deltaTime受Time.timeScale的影响,Time.unscaledDeltaTime不受Time.timeScale的影响。
具体代码
TimerSys和Timer
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TimerSys
{
private static TimerSys _instance;
public static TimerSys Instance
{
get
{
if (_instance == null)
{
_instance = new TimerSys();
}
return _instance;
}
}
private List<Timer> _timerList;
public TimerSys()
{
_timerList = new List<Timer>();
MonoSys.Instance.AddUpdateEvent(OnUpdateEvent);
}
public void Destroy()
{
MonoSys.Instance?.RemoveUpdateEvent(OnUpdateEvent);
Clear();
_timerList = null;
}
public void Clear()
{
if (_timerList == null)
{
return;
}
foreach (var timer in _timerList)
{
timer.Destroy();
}
_timerList.Clear();
}
public Timer CreateTimer(bool shouldImmediateStart = true, bool shouldIgnoreTimeScale = false)
{
Timer timer = new Timer(shouldImmediateStart, shouldIgnoreTimeScale);
_timerList.Add(timer);
return timer;
}
public bool DestroyTimer(Timer timer)
{
bool destroySuccessfully = false;
if (_timerList.Contains(timer))
{
timer.Destroy();
_timerList.Remove(timer);
destroySuccessfully = true;
}
return destroySuccessfully;
}
private void OnUpdateEvent()
{
if (_timerList != null && _timerList.Count > 0)
{
for (int i = 0; i < _timerList.Count; i++)
{
if (_timerList[i] != null)
{
_timerList[i].UpdateTime();
}
}
}
}
}
public class Timer
{
private float _time;
public float Time
{
get { return _time; }
}
private readonly bool ShouldIgnoreTimeScale;
public bool IsPaused{ get; private set; }
public event Action<float> TimeChangedEvent;
public event Action PauseEvent;
public event Action ContinueEvent;
public Timer(bool shouldImmediateStart, bool shouldIgnoreTimeScale)
{
ShouldIgnoreTimeScale = shouldIgnoreTimeScale;
if (shouldImmediateStart)
{
BeginTime();
}
else
{
Pause();
}
}
public void Destroy()
{
}
// 修改时间
public void UpdateTime()
{
if (!IsPaused)
{
if (ShouldIgnoreTimeScale)
{
ChangeTime(_time + UnityEngine.Time.unscaledDeltaTime);
}
else
{
ChangeTime(_time + UnityEngine.Time.deltaTime);
}
}
}
private void ChangeTime(float time)
{
_time = time;
TimeChangedEvent?.Invoke(_time);
}
// 开始计时
public void BeginTime()
{
Reset();
Continue();
}
// 停止计时
public void Pause()
{
IsPaused = true;
PauseEvent?.Invoke();
}
// 继续计时
public void Continue()
{
IsPaused = false;
ContinueEvent?.Invoke();
}
// 重置时间
public void Reset()
{
ChangeTime(0f);
}
// 格式化显示
public static string FormatStr(float time)
{
int intTime = (int)time;
int hour = intTime / 3600;
int minute = (intTime - 3600 * hour) / 60;
int second = intTime - 3600 * hour - 60 * minute;
string hourStr = hour.ToString().PadLeft(2, '0');
string minuteStr = minute.ToString().PadLeft(2, '0');
string secondStr = second.ToString().PadLeft(2, '0');
string timeStr = string.Format("{0}:{1}:{2}", hourStr, minuteStr, secondStr);
return timeStr;
}
}
MonoSys
用途:让不继承MonoBehaviour能使用MonoBehaviour提供的一些方法。(通过注册事件的方式)
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MonoController : MonoBehaviour
{
public event Action ApplicationPauseEvent;
public event Action ApplicationQuitEvent;
public event Action UpdateEvent;
private void OnApplicationPause(bool pauseStatus)
{
if (pauseStatus)
{
ApplicationPauseEvent?.Invoke();
}
}
private void OnApplicationQuit()
{
ApplicationQuitEvent?.Invoke();
}
private void Update()
{
UpdateEvent?.Invoke();
}
}
public class MonoSys
{
private static MonoSys _instance;
public static MonoSys Instance
{
get
{
if (_instance == null)
{
_instance = new MonoSys();
}
return _instance;
}
}
private MonoController _monoController;
private MonoSys()
{
var parentGo = GameObject.Find("Singleton");
if (parentGo == null)
{
parentGo = new GameObject("Singleton");
UnityEngine.Object.DontDestroyOnLoad(parentGo);
}
GameObject go = new GameObject(nameof(MonoController));
go.transform.SetParent(parentGo.transform);
_monoController = go.AddComponent<MonoController>();
}
public Coroutine StartCoroutine(IEnumerator routine)
{
return _monoController.StartCoroutine(routine);
}
public void StopCoroutine(IEnumerator routine)
{
_monoController.StopCoroutine(routine);
}
public void AddApplicationQuitEvent(Action action)
{
_monoController.ApplicationQuitEvent += action;
}
public void RemoveApplicationQuitEvent(Action action)
{
_monoController.ApplicationQuitEvent -= action;
}
public void AddApplicationPauseEvent(Action action)
{
_monoController.ApplicationPauseEvent += action;
}
public void RemoveApplicationPauseEvent(Action action)
{
_monoController.ApplicationPauseEvent -= action;
}
public void AddUpdateEvent(Action action)
{
_monoController.UpdateEvent += action;
}
public void RemoveUpdateEvent(Action action)
{
_monoController.UpdateEvent -= action;
}
}