[英]Unity Coroutine Wait Until true for x seconds
我想实现类似于yield return new WaitUntil(() => Check());
的东西。 , 但有一个额外的补充。 在满足Check()
条件后,如果条件仍然为真,它应该等待 x 秒检查每一帧。
这是我的实现:
private IEnumerator CheckCor(float waitTime)
{
bool checkFlag = true;
bool checkFlag2;
float whileTime;
while (checkFlag)
{
yield return new WaitUntil(() => Check());
checkFlag2 = true;
whileTime = waitTime;
while (whileTime > 0)
{
if (!Check())
{
checkFlag2 = false;
}
whileTime -= Time.deltaTime;
yield return null;
}
if (checkFlag2)
{
checkFlag = false;
}
}
}
Check()
在哪里
private bool Check();
我的实现工作得很好,但似乎有点长。
有没有更短的方法来实现相同的行为?
(也使其通用将是一个加号,例如yield return WaitUntilForSeconds(Check(), 3f);
,其中 Check() 是条件,而 3f 是检查每一帧条件的时间。我猜它可以使用CustomYieldInstruction
,但我不确定它是如何工作的。)
将其实现为CustomYieldInstruction
并不算太糟糕。 将检查器作为Func<bool>
传入,保留一个标志以记住您是否已启动计时器,并在检查 function 在任何时候返回 false 时重置该标志。 您甚至可以接受Func<float>
在计时器重置时调用剩余时间:
using UnityEngine;
public class WaitUntilForSeconds: CustomYieldInstruction
{
float pauseTime;
float timer;
bool waitingForFirst;
Func<bool> myChecker;
Action<float> onInterrupt;
bool alwaysTrue;
public WaitUntilForSeconds(Func<bool> myChecker, float pauseTime,
Action<float> onInterrupt = null)
{
this.myChecker = myChecker;
this.pauseTime = pauseTime;
this.onInterrupt = onInterrupt;
waitingForFirst = true;
}
public override bool keepWaiting
{
get
{
bool checkThisTurn = myChecker();
if (waitingForFirst)
{
if (checkThisTurn)
{
waitingForFirst = false;
timer = pauseTime;
alwaysTrue = true;
}
}
else
{
timer -= Time.deltaTime;
if (onInterrupt != null && !checkThisTurn && alwaysTrue)
{
onInterrupt(timer);
}
alwaysTrue &= checkThisTurn;
// Alternate version: Interrupt the timer on false,
// and restart the wait
// if (!alwaysTrue || timer <= 0)
if (timer <= 0)
{
if (alwaysTrue)
{
return false;
}
else
{
waitingForFirst = true;
}
}
}
return true;
}
}
}
然后,您可以使用
yield return new WaitUntilForSeconds(Check, 3f);
// or
yield return new WaitUntilForSeconds(Check, 3f, (float t) => {Debug.Log($"Interrupted with {t:F3} seconds left!");});
如果您需要检查器的参数,您可以使用无参数 lambda:
yield return new WaitUntilForSeconds(() => Check(Vector3.up), 3f);
而且,与 lambda 一样,请注意您所做的任何变量捕获。
如果您不想要整个CustomYieldInstruction
,我会使用另一个WaitUntil
来暂停:
private IEnumerator CheckCor(float waitTime)
{
bool stillWaiting = true;
while (stillWaiting)
{
yield return new WaitUntil(() => Check());
float pauseTime = waitTime;
yield return new WaitUntil(() =>
{
pauseTime -= Time.deltaTime;
stillWaiting = !Check();
return stillWaiting || pauseTime <= 0;
});
if (stillWaiting)
{
// Stuff when pause is interrupted goes here
}
}
// Stuff after pause goes here
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.