Unity中控制延时的方法有哪些?
What are ways to control the time delay in Unity?
我环顾四周,显然我可以在这些库/解决方案之间做出选择:
一个:
public void Awake() {
Invoke("InvokeAndPrint", 2);
}
void InvokeAndPrint() {
print("InvokeAndPrint 2");
}
两个:
void Start() {
StartCoroutine(WaitAndPrint(2.0F));
}
IEnumerator WaitAndPrint(float waitTime) {
yield return new WaitForSeconds(waitTime);
print("WaitAndPrint " + Time.time);
}
我想知道有没有其他更好的方法?
这是我对以上评论的总结
我能想到的唯一其他方法是老式的在开始时记下时间;然后在您的 Update()
方法中检查经过的时间。你基本上自己做所有事情。虽然比上面的例子更冗长,但它是类型安全的,不需要任何额外的线程或线程作业对象。
最简单
首先我们需要定义一些字段:
private DateTime _start;
private bool _done;
开始时记下时间:
void Start()
{
_start = DateTime.Now;
}
...然后在您的更新中检查已经过了多少时间。如果它大于你的超时时间,比如 2 秒,请关闭你想做的任何事情 - 在这种情况下 print()
:
void Update()
{
if (! _done && (DateTime.Now - _start).TotalSeconds >= 2)
{
print("hello world");
_done = true;
}
}
就是这样。
可重用代码
您可能会发现有很多地方需要这样做,所以如果有一种方法可以减少重复代码,岂不是 groovy。也许 class 可以将其包裹起来?
class DelayedJob
{
private readonly TimeSpan _delay;
private readonly Action _action;
private readonly DateTime _start;
public DelayedJob(TimeSpan delay, Action action)
{
if (action == null)
{
throw new ArgumentNullException("action");
}
_delay = delay;
_action = action;
_start = DateTime.Now;
}
/// <summary>
/// Updates this instance.
/// </summary>
/// <returns>true if there is more work to do, false otherwise</returns>
public bool Update()
{
if (DateTime.Now - _start >= _delay)
{
_action();
return false;
}
return true;
}
}
那么你可以这样做:
void Start()
{
_job = new DelayedJob(TimeSpan.FromSeconds(2), ()=> print("hello"));
}
...相应地更新您的 Update()
后:
void Update()
{
if (_job != null && !_job.Update())
{
_job = null;
}
}
多项工作
只需将它们放在一个集合中并在运行时进行处理即可。
private List<DelayedJob> _jobs;
void Start()
{
_jobs = new List<DelayedJob>
{
new DelayedJob(TimeSpan.FromSeconds(2), () => print("star wars")),
new DelayedJob(TimeSpan.FromSeconds(3f), () => print("is coming!"))
};
}
...Update()
的一些改动:
void Update()
{
bool again;
do
{
again = false;
// you probably want to optimise this so that we don't check the same items
// at the start again after removing an item
foreach (var delayedJob in _jobs)
{
if (!delayedJob.Update())
{
_jobs.Remove(delayedJob);
again = true; // start over
break;
}
}
}
while (again);
}
我环顾四周,显然我可以在这些库/解决方案之间做出选择:
一个:
public void Awake() {
Invoke("InvokeAndPrint", 2);
}
void InvokeAndPrint() {
print("InvokeAndPrint 2");
}
两个:
void Start() {
StartCoroutine(WaitAndPrint(2.0F));
}
IEnumerator WaitAndPrint(float waitTime) {
yield return new WaitForSeconds(waitTime);
print("WaitAndPrint " + Time.time);
}
我想知道有没有其他更好的方法?
这是我对以上评论的总结
我能想到的唯一其他方法是老式的在开始时记下时间;然后在您的 Update()
方法中检查经过的时间。你基本上自己做所有事情。虽然比上面的例子更冗长,但它是类型安全的,不需要任何额外的线程或线程作业对象。
最简单
首先我们需要定义一些字段:
private DateTime _start;
private bool _done;
开始时记下时间:
void Start()
{
_start = DateTime.Now;
}
...然后在您的更新中检查已经过了多少时间。如果它大于你的超时时间,比如 2 秒,请关闭你想做的任何事情 - 在这种情况下 print()
:
void Update()
{
if (! _done && (DateTime.Now - _start).TotalSeconds >= 2)
{
print("hello world");
_done = true;
}
}
就是这样。
可重用代码
您可能会发现有很多地方需要这样做,所以如果有一种方法可以减少重复代码,岂不是 groovy。也许 class 可以将其包裹起来?
class DelayedJob
{
private readonly TimeSpan _delay;
private readonly Action _action;
private readonly DateTime _start;
public DelayedJob(TimeSpan delay, Action action)
{
if (action == null)
{
throw new ArgumentNullException("action");
}
_delay = delay;
_action = action;
_start = DateTime.Now;
}
/// <summary>
/// Updates this instance.
/// </summary>
/// <returns>true if there is more work to do, false otherwise</returns>
public bool Update()
{
if (DateTime.Now - _start >= _delay)
{
_action();
return false;
}
return true;
}
}
那么你可以这样做:
void Start()
{
_job = new DelayedJob(TimeSpan.FromSeconds(2), ()=> print("hello"));
}
...相应地更新您的 Update()
后:
void Update()
{
if (_job != null && !_job.Update())
{
_job = null;
}
}
多项工作
只需将它们放在一个集合中并在运行时进行处理即可。
private List<DelayedJob> _jobs;
void Start()
{
_jobs = new List<DelayedJob>
{
new DelayedJob(TimeSpan.FromSeconds(2), () => print("star wars")),
new DelayedJob(TimeSpan.FromSeconds(3f), () => print("is coming!"))
};
}
...Update()
的一些改动:
void Update()
{
bool again;
do
{
again = false;
// you probably want to optimise this so that we don't check the same items
// at the start again after removing an item
foreach (var delayedJob in _jobs)
{
if (!delayedJob.Update())
{
_jobs.Remove(delayedJob);
again = true; // start over
break;
}
}
}
while (again);
}