介绍
在Unity3D中进行延迟执行操作
这个库经过多次项目的战斗测试和改进,包括屡获殊荣的Pitfall Planet
由Alexander Biggs + Adam Robinson-Yu撰写。
源码工程
安装
要获取UnityTimer的最新版本,请转到Releases页面并从最新版本下载Timer.unitypackage文件。然后,如果打开Unity项目,则可以打开.unitypackage文件以将脚本安装到项目中。
或者,如果您希望保持最新版本,可以将此存储库克隆到项目的Assets文件夹中。但是,我们不保证这会给你一个稳定的版本。
基本例子
Unity Timer提供了以下创建计时器的方法:
/// < summary >
///注册一个新的计时器,该计时器应在经过一段时间后触发事件。/// </ summary >
/// < param name = “ duration ” >计时器在触发之前应等待的时间,以秒为单位。</ param >
/// < param name = “ onComplete ” >要触发的动作当计时器完成时。</ param >
public static Timer Register(float duration, Action onComplete);
调用方法像这样:
//在5秒之后打印 "Hello World".
Timer.Register(5f, () => Debug.Log("Hello World"));
动机
开箱即用,如果没有这个库,在Unity中有两种主要的处理定时器的方法:
1.使用带有WaitForSeconds方法的协程。
2.将计时器启动的时间存储在私有变量中(例如startTime = Time.time),然后检查更新调用if(Time.time - startTime >= timerDuration)。
第一种方法很冗长,迫使您重构代码以使用IEnumerator函数。此外,它需要访问MonoBehaviour实例来启动协程,这意味着该解决方案不适用于非MonoBehaviour类。最后,没有办法阻止WaitForSeconds受到TimeScale变化的影响。
第二种方法容易出错,并且隐藏了您尝试表达的实际游戏逻辑,使得代码不易于阅读。
这个库缓解了这两个问题,使您可以轻松地为Unity项目中的任何类添加易于阅读,富有表现力的计时器。
特性
通过设置isLooped
为true 使计时器重复。
//每两秒钟调用一下玩家的跳转方法。
Timer.Register(2f, player.Jump, isLooped: true);
调用后取消定时器。
Timer timer;
void Start()
{
timer = Timer.Register(2f, () => Debug.Log("You won't see this text if you press X."));
}
void Update()
{
if (Input.GetKeyDown(KeyCode.X)) {
Timer.Cancel(timer);
}
}
通过设置useRealTime
为true,通过realtimeSinceStartup测量时间而不是用Time.Scale。
//假设您通过将时间刻度设置为0来暂停游戏。
Time.timeScale = 0f;
//...然后设置useRealTime,这样即使游戏时间没有进行,这个计时器仍然会启动。
Timer.Register(1f, this.HandlePausedGameState, useRealTime: true);
将计时器附加到MonoBehaviour,以便在MonoBehaviour时销毁计时器。
通常,从MonoBehaviour调用的计时器将操纵该行为的状态。因此,通常的做法是取消MonoBehaviour的OnDestroy方法中的计时器。我们添加了一个方便的扩展方法,将Timer连接到MonoBehaviour,这样当MonoBehaviour被检测为null时它会自动取消定时器。
public class CoolMonoBehaviour : MonoBehaviour
{
void Start()
{
// 使用 AttachTimer拓展方法创建一个Timer,当对象销毁时,这个Timer也会被销毁。
this.AttachTimer(5f, () =>
{
//如果此代码在对象被销毁后运行,则会抛出一个空引用,
// 这可能会破坏游戏状态。
this.gameObject.transform.position = Vector3.zero;
});
}
void Update()
{
// 此代码可以随时销毁对象!
if (Input.GetKeyDown(KeyCode.X))
{
GameObject.Destroy(this.gameObject);
}
}
}
使用onUpdate回调逐步更新值。
// 在五秒钟内将颜色从白色变为红色。
Color color = Color.white;
float transitionDuration = 5f;
Timer.Register(transitionDuration,
onUpdate: secondsElapsed => color.r = 255 * (secondsElapsed / transitionDuration),
onComplete: () => Debug.Log("Color is now red"));
还包括许多其他有用的功能
- timer.Pause()
- timer.Resume()
- timer.GetTimeRemaining()
- timer.GetRatioComplete()
- timer.isDone
在Timer / Example文件夹中包含演示所有功能的测试场景脚本。
使用说明/注意事项
- 这个库目前似乎不适用于Hololens。我们正在寻找解决方案。
- 更改场景时,所有计时器都会被销毁。通常需要这种行为,并且它发生的原因是定时器由TimerController更新,TimerController在场景发生变化时也会被破坏。请注意,因此,在关闭场景时(例如在对象的OnDestroy方法中)创建Timer将导致在生成TimerController时出现Unity错误。。