【发布时间】:2013-06-03 22:16:23
【问题描述】:
我正在实现一个用于运行游戏 AI 脚本的光纤系统,但遇到了一个小问题。
我在脚本中使用 yield return x 来表示等待 x 帧。我想封装计算 x 帧的逻辑,因为其他事件可以修改要等待的帧数。我理想的解决方案如下:
public Boolean removeScript = false;
public IEnumerable update()
{
while(true)
{
shootAtPlayer()
wait(30)
}
}
private IEnumerable wait(int x)
{
yield return removeScript ? -1 : x;
}
wait() 要么指示产生返回 30,要么在不再需要脚本时返回 -1。迭代器将通过删除脚本来处理 -1 返回。如果 x > 0,迭代器将每帧递减返回值直到 0,然后再次调用 update()。
但是这不起作用,因为从 wait() 返回的 yield 当然不会传播到 update 方法。这会导致代码重复、模块性变差和代码可读性降低:
public IEnumerable update()
{
while(true)
{
shootAtPlayer()
yield return removeScript ? -1 : x;
}
}
我想知道是否有更好的方法来构建它?还是我缺少在这种情况下有用的语言功能?
【问题讨论】:
-
在这里使用
yield return到底有什么意义?谁打电话给update,为什么它不能只是一个普通的旧函数? -
调用者有一个更新循环(每帧调用一次),如果当前枚举数为 0,则在上述脚本上调用更新。如果当前枚举数 > 0,则每帧递减一次枚举数,直到 0 . 以这种方式实现的原因是允许脚本在执行此操作然后等待 60 帧然后执行此方式而不是在第 0 帧执行此操作然后在第 60 帧执行此操作。它使脚本更多易于跟踪,因为它们操作类似于单独的子程序。最好使用 yield return 而不是为每个脚本生成一个线程并使用 sleep 等
-
您正在尝试使用 yield 创建协程。不幸的是,yield 是一个略微受限的协同例程版本。正如您所发现的,您只能在 IEnumerable 函数的主体内直接使用 yield,而不是嵌套到另一个方法中。如果您考虑一下编译器在幕后做了什么魔法,这个限制是有道理的。
标签: c# yield-return