unity3d 停止在IEnumerator中启动的协同程序会阻止执行IEnumerator的剩余部分?

zwghvu4y  于 2022-12-23  发布在  其他
关注(0)|答案(2)|浏览(220)

我在努力确保某种功能,完成可视化()在couroutine完成后运行。如果我让couroutine自然地完成,它会工作得很好。如果我对通过字典传回的协程值调用StopCoroutine,则函数在yield返回后的后半部分不会触发。我会认为停止第一个内部协程会导致它继续通过块的其余部分,因为我没有停止父协程?

public IEnumerator StartVisualCommandCoroutine(Dictionary<IVisualCommand, Coroutine> dictionary)
{
    Coroutine c = _asyncProcessor.StartCoroutine(_visualCommand.PlayVisualCommand());
    dictionary.Add(_visualCommand, c); //a janky way to pass the coroutine itself back so we can StopCoroutine it if we want it to end prematurely
    yield return c;
    _visualCommand.FinalizeVisual(); //this runs if the coroutine ends naturally, but not if we called StopCoroutine on c
 }
1l5u6lss

1l5u6lss1#

您试图在yield返回调用后执行命令,但这不会起作用,通常IDE会警告您代码部分不可访问。只需将_visualCommand.FinalizeVisual()上移一行即可。
附注:一般来说,你在这里使用协程的方式是非常非常低效的(因为它们通常是这样的),尝试探索一下UniTask来满足你的需要,这是一个很棒的Unity异步框架包,会让你的生活变得更容易。如果你不想弄乱这个包,有一堆关于如何使用async/await(即https://www.youtube.com/watch?v=WY-mk-ZGAq8)的教程。

3qpi33ja

3qpi33ja2#

我只能猜测,但我认为它将继续yield,因为您中断的例程实际上从未完成。
一般来说,我会建议使用相同的技术,你通常会用在真实的的异步代码和去一个CancellationToken一样,例如。

public IEnumerator StartVisualCommandCoroutine(Dictionary<IVisualCommand, CancellationTokenSource> dictionary)
{
    var tokenSource = new CancellationTokenSource();
    dictionary.Add(_visualCommand, tokenSource);
    yield return _visualCommand.PlayVisualCommand(tokenSource.Token);
    _visualCommand.FinalizeVisual();
 }

然后为了停止你做的某件事

yourDictionary[someKey].Cancel();

现在,你不再肮脏地杀死一个例程,而是在你让步的时候干净地终止它。

yield return new WaitForSeconds(3f);

转变为

for(var timePassed = 0f; timePassed < 3f; timePassed += Tome.deltaTime) 
{
    if(cancellationToken.IsCancellationRequested) yield break;

    yield return null;
}

if(cancellationToken.IsCancellationRequested) yield break;

这样,您可以完全控制在完全取消例程的情况下仍应执行的内容。
不过我同意Xander's recommendations,并建议您查看UniTask,它集成起来很简单,并为异步和同步操作提供了很好的异步/可等待 Package 器,例如,在您的情况下,还允许使用try - catch - finally

相关问题