![](/img/trans.png)
[英]C# Class is IEnumerable AND an IEnumerator at the same time. What are the issues with this?
[英]What Is an IEnumerator In C# and what is it used for in Unity?
最近看到Unity中使用C#生成对象的教程。 因为老师像这样使用了 function
public IEnumerator CallSpawner()
{
yield return new WaitForSeconds(0.5f);
SpawnObstacles();
}
我想问一下IEnumerator function有什么用,难道不能通过这个流程
float diffTime = 0f;
private void Update()
{
if(Time.time - diffTime == 0.5f)
{
diffTime = Time.time;
SpawnObstacles();
}
}
我阅读了文档但无法理解..
IEnumerator function有什么用
IEnumerator
没有 function,它是一个返回类型。 C# 也没有函数(但我知道你的意思)——在 C# 中我们称它们为方法。
I Enumerator 被称为意味着它是一个接口,所以任何实现 IEnumerator 接口的 class 都可以通过该方法返回
实际上,在这种使用中,它实际上更像是一种 hack,而不是打算提供枚举器的真实意图,即逐步步枪通过(或生成)事物的集合。
当您在方法中使用yield return
语句时,“发生了一些魔法”,这不是经典意义上的return
,而是创建了一个工具,代码可以从它停止的地方恢复(调用返回的枚举器中的下一个项目将导致代码从 yield 之后恢复,而不是重新开始)。
如果您查看 MSDN 的 yield 示例:
public class PowersOf2
{
static void Main()
{
// Display powers of 2 up to the exponent of 8:
foreach (int i in Power(2, 8))
{
Console.Write("{0} ", i);
}
}
public static System.Collections.Generic.IEnumerable<int> Power(int number, int exponent)
{
int result = 1;
for (int i = 0; i < exponent; i++)
{
result = result * number;
yield return result;
}
}
// Output: 2 4 8 16 32 64 128 256
}
循环由i
控制; 如果这不是yield return
那么这将不是预期的 function (它不能返回一个开始的枚举器,但我们将忽略它)。 假设它只是一个正常的return
,循环根本不会循环; 代码会进入,开始循环,点击return
,然后只返回一个数字一次,循环所在的所有 memory 都会被遗忘。
通过使它成为yield return
,返回一个枚举器,并设置一小组“保存状态”,循环可以记住i
的当前值 - 每次您要求下一个值时,代码从它所在的位置恢复离开(即在 yield 之后),循环再次循环并产生不同的值。 这当然会一直持续到最大值。此时返回的枚举器说它没有更多的项目
您也可以永远屈服。如果代码永远无法逃脱循环,那么它将永远屈服/生成
在这种情况下,您必须使用yield return new WaitForSeconds
因为这就是 WaitForSeconds 的工作方式。 Yielding 将一个枚举器放弃给调用方法,然后调用方法可以自由地枚举它。 从文档看来,这是故意在下一帧完成的,因此使用 yield(可能重复)是一种安排跨多个帧出现的代码块的方法,而无需某种外部 state 管理来记住进程在哪里最多和罗嗦
你可以
我们不能通过这个过程来做吗
当然,看起来很合理; 每秒看时钟 100 次,如果自从您第一次看时钟后已经过去 0.5 秒,则生成障碍物
我想(从未使用过 Unity;除了阅读这个函数的文档之外,不要自称对它一无所知)您的更新循环还有很多事情要做,所以将一个过程交给专心等待然后做比花所有时间看时钟并进行可能复杂的计算以计算是否应该做某事更有效; 生活中大多数以每 x 毫秒轮询开始的事情都受益于切换到“如果事件发生,对其做出反应”的工作方式
您正在查看的代码仅存在于 Unity3d 和 DotNet Framework < 4.0 中。
您找不到任何文档的原因是:
async
/ await
。 不幸的是,Unity3d 是基于旧版本的 Mono,它不支持async
/ await
。
幸运的是, async
/ await
的大部分功能都可以使用这种方法来完成
go 使用 Jeff 的 Power Threading Library 方法有几个原因。
SpawnObstacles()
运行一次后检查 0.5 长。但主要原因必须是 Flow。 在这个非常简单的例子中,我们不会轻易混淆。 但是想象一下下面的效果。
这将很难用update
方法编写。
但是,您可以使用 IEnumerable 轻松完成。
public IEnumerator CallSpawner()
{
int current = 1;
int last = 0;
while(true)
{
yield return new WaitForSeconds(10f);
SpawnEnemies(current);
var next = current + last;
last = current;
current = next;
}
}
作为奖励,您会注意到所有变量都很好地封装在方法中,而不是在自由浮动字段中。
这意味着您可以运行多个 CallSpawner() 而不会受到它们的干扰。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.