gpt4 book ai didi

c# - Unity 协程等待 x 秒直到 true

转载 作者:行者123 更新时间:2023-12-03 08:27:26 29 4
gpt4 key购买 nike

我想实现一些类似于 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> 传递,保留一个标志来记住您是否已启动计时器,并在检查函数在任何时候返回 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 一样,be aware of any variable capture you do .


如果您不想要整个 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
}

关于c# - Unity 协程等待 x 秒直到 true,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66228216/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com