计时器效果图:
Timer用法:
第一种:脚本加到物体上,勾选"自动计时"。
第二种:脚本加到物体上,调用timer.start()方法启动。
第三种:代码中动态添加Timer脚本。
using UnityEngine;
public class TimerTest : MonoBehaviour {
private void Start () {
// 创建一个Timer并开始计时
gameObject.AddComponent<Timer>().start(1.5f, onTimeup);
// 倒计时3秒
gameObject.AddComponent<Timer>().start(1, 3, onCD, onCDEnd);
// 无限计数(repeatCount为<=0时 无限重复)
gameObject.AddComponent<Timer>().start(1, -1, onCount, null);
// Timer API
Timer timer = gameObject.AddComponent<Timer>();
timer.delay = 10;// 延迟10秒开始
timer.start(); // 开始计时
timer.stop(); // 暂停计时
timer.reset(); // 重置已计时的时间和次数
timer.restart();// 重新开始计时 reset() + start()
}
/// <summary> 正常计时 </summary>
private void onTimeup(Timer timer) {
print("计时完成");
}
/// <summary> 倒计时间隔 </summary>
private void onCD(Timer timer) {
print(timer.repeatCount - timer.currentCount); // 3, 2, 1
}
/// <summary> 倒计时结束 </summary>
private void onCDEnd(Timer timer) {
print(timer.repeatCount - timer.currentCount); // 0
}
/// <summary> 无限计数 </summary>
private void onCount(Timer timer) {
print(timer.currentCount); // 1, 2, 3……
}
}
Timer API:
// 开始/继续计时
public void start() {}
// 暂停计时
public void stop() {}
// 停止Timer并重置数据
public void reset() {}
// 重置数据并重新开始计时
public void restart() {}
// 开始计时 time时间(秒) onComplete(Timer timer)计时完成回调事件
public void start(float time, TimerCallback onComplete) {}
// 开始计时 interval计时间隔 repeatCount重复次数 onComplete(Timer timer)计时完成回调事件
public void start(float interval, int repeatCount, TimerCallback onComplete) {}
// 开始计时 interval计时间隔 repeatCount重复次数
// onInterval(Timer timer)计时间隔回调事件
// onComplete(Timer timer)计时完成回调事件
public void start(float interval, int repeatCount, TimerCallback onInterval, TimerCallback onComplete) {}
Timer.cs
using UnityEngine;
using UnityEngine.Events;
/// <summary>
/// 计时器
/// <para>ZhangYu 2018-04-08</para>
/// </summary>
public class Timer : MonoBehaviour {
// 延迟时间(秒)
public float delay = 0;
// 间隔时间(秒)
public float interval = 1;
// 重复次数
public int repeatCount = 1;
// 自动计时
public bool autoStart = false;
// 自动销毁
public bool autoDestory = true;
// 当前时间
public float currentTime = 0;
// 当前次数
public int currentCount = 0;
// 计时间隔
public UnityEvent onIntervalEvent;
// 计时完成
public UnityEvent onCompleteEvent;
// 回调事件代理
public delegate void TimerCallback(Timer timer);
// 上一次间隔时间
private float lastTime = 0;
// 计时间隔
private TimerCallback onIntervalCall;
// 计时结束
private TimerCallback onCompleteCall;
private void Start () {
enabled = autoStart;
}
private void FixedUpdate () {
if (!enabled) return;
addInterval(Time.deltaTime);
}
/// <summary> 增加间隔时间 </summary>
private void addInterval(float deltaTime) {
currentTime += deltaTime;
if (currentTime < delay) return;
if (currentTime - lastTime >= interval) {
currentCount++;
lastTime = currentTime;
if (repeatCount <= 0) {
// 无限重复
if (currentCount == int.MaxValue) reset();
if (onIntervalCall != null) onIntervalCall(this);
if (onIntervalEvent != null) onIntervalEvent.Invoke();
} else {
if (currentCount < repeatCount) {
//计时间隔
if (onIntervalCall != null) onIntervalCall(this);
if (onIntervalEvent != null) onIntervalEvent.Invoke();
} else {
//计时结束
stop();
if (onCompleteCall != null) onCompleteCall(this);
if (onCompleteEvent != null) onCompleteEvent.Invoke();
if (autoDestory && !enabled) Destroy(this);
}
}
}
}
/// <summary> 开始/继续计时 </summary>
public void start() {
enabled = autoStart = true;
}
/// <summary> 开始计时 </summary>
/// <param name="time">时间(秒)</param>
/// <param name="onComplete(Timer timer)">计时完成回调事件</param>
public void start(float time, TimerCallback onComplete) {
start(time, 1, null, onComplete);
}
/// <summary> 开始计时 </summary>
/// <param name="interval">计时间隔</param>
/// <param name="repeatCount">重复次数</param>
/// <param name="onComplete(Timer timer)">计时完成回调事件</param>
public void start(float interval, int repeatCount, TimerCallback onComplete) {
start(interval, repeatCount, null, onComplete);
}
/// <summary> 开始计时 </summary>
/// <param name="interval">计时间隔</param>
/// <param name="repeatCount">重复次数</param>
/// <param name="onInterval(Timer timer)">计时间隔回调事件</param>
/// <param name="onComplete(Timer timer)">计时完成回调事件</param>
public void start(float interval, int repeatCount, TimerCallback onInterval, TimerCallback onComplete) {
this.interval = interval;
this.repeatCount = repeatCount;
onIntervalCall = onInterval;
onCompleteCall = onComplete;
reset();
enabled = autoStart = true;
}
/// <summary> 暂停计时 </summary>
public void stop() {
enabled = autoStart = false;
}
/// <summary> 停止Timer并重置数据 </summary>
public void reset(){
lastTime = currentTime = currentCount = 0;
}
/// <summary> 重置数据并重新开始计时 </summary>
public void restart() {
reset();
start();
}
}
TimerEditor.cs
using UnityEditor;
using UnityEngine;
/// <summary>
/// 计时器 编辑器
/// <para>ZhangYu 2018-04-08</para>
/// </summary>
[CanEditMultipleObjects]
[CustomEditor(typeof(Timer))]
public class TimerEditor : Editor {
public override void OnInspectorGUI() {
Timer script = (Timer)target;
// 重绘GUI
EditorGUI.BeginChangeCheck();
// 公开属性
drawProperty("delay", "延迟时间(秒)");
drawProperty("interval", "间隔时间(秒)");
drawProperty("repeatCount", "重复次数");
if (script.repeatCount <= 0) EditorGUILayout.LabelField(" ", "<=0 时无限重复", GUILayout.ExpandWidth(true));
EditorGUILayout.BeginHorizontal();
drawProperty("autoStart", "自动计时");
drawProperty("autoDestory", "自动销毁");
EditorGUILayout.EndHorizontal();
// 只读属性
GUI.enabled = false;
drawProperty("currentTime", "当前时间(秒)");
drawProperty("currentCount", "当前次数");
GUI.enabled = true;
// 回调事件
drawProperty("onIntervalEvent", "计时间隔事件");
drawProperty("onCompleteEvent", "计时完成事件");
if (EditorGUI.EndChangeCheck()) serializedObject.ApplyModifiedProperties();
}
private void drawProperty(string property, string label) {
EditorGUILayout.PropertyField(serializedObject.FindProperty(property), new GUIContent(label), true);
}
}
转载请注明原文出处:https://segmentfault.com/a/11...