Unity3D 协程的For循环

我正在用Unity3D,使用的是C#,我正在尝试着写一个For循环,在一个循环中实例化多个游戏对象,但是我想稍微交错实例化,在下一个游戏对象实例化之前,比如说0.5秒,
我认为这和做一个单循环一样简单 :

for (int i = 0; i <= 3; i++)
            {
                Instantiate(gameObject, objectSpawn[i].transform.position, Quaternion.identity);
                StartCoroutine(WeaponsCooldown(6));
            }
            StartCoroutine(WeaponsCooldown(2));

在协程中,有个切换案例,所以我可以重复多次使用。

IEnumerator WeaponsCooldown(int coolTrigger)
{
    switch (coolTrigger)
    {
    case 1:
        mainFire = true;
        yield return new WaitForSeconds(5);
        mainFire = false;
        break;

    case 2:
        leftFire = true;
        yield return new WaitForSeconds(3);
        leftFire = false;
        break;
...down to case 6 (for this project)

我得到的结果是这样的: For循环之外的StartCoroutine能够很好地激发,这是武器的主冷却时间,保证player不断地朝它发射。然而,For循环之内的StartCoroutine似乎并没有减缓For循环,由于我刚接触Unity和C#,所以我不知道如何找出错在哪里。
我假设StartCoroutine是一个单独的线程,除了运行Update线程,那是For循环仍在继续的原因,因为它不会等待线程结束。
如果是这样的话,有什么解决方法呢?
我想在一个脚本内完成的原因是:player可以有25个以上的硬点,这样可以更加简单的用较少的硬点重用多个船只,对于我个人来说也会更加方便一点。
先谢过!

原问题:Unity3d - Coroutine in For Loop

阅读 17.9k
2 个回答

Heisenbug:
For循环中的startcoroutine似乎不会减缓For循环。
你的脚本得到的结果是在同一帧中实例化所有的GameObject,并开始所有的协同程序(不同的冷却持续不同的时间)。
假设除了Update 线程以外,StartCoroutine是一个单独运行的线程。这是For循环继续的原因,因为它不会等待协程来完成。
协程在所有的线程中有用。它们是迭代器块(iterator blocks)
引用一下 Jon Skeet的话:

在 C# 2, 当你使用迭代器块来执行 IEnumerable 或 IEnumerator(或通用表格)编译器会为你完成所有的复杂工作。它建立一个状态机,在迭代器块中,迭代器有效的获得执行代码,随着它的运行yield值。

另一个描述它的方法是协同式多任务(cooperative multitasking)。

我在尝试写一个For循环,在1 个循环中实例化所有的游戏对象,但是我只想稍微错开它们的实例化,比如0.5秒,在下一个游戏对象实例化之前。

不考虑实现过程中的具体行为,有个简单的方法可以延迟实例化调用(0.5秒):在协程自身中wrap For循环。

public IEnumerator DelayInstantiate()
{
  for (int i = 0; i <= 3; i++)
  {
     Instantiate(gameObject, objectSpawn[i].transform.position, Quaternion.identity);
     StartCoroutine(WeaponsCooldown(6)); //or do what you want

     yield return new WaitForSeconds(0.5f);
  }
}
新手上路,请多包涵

你的假设不对,协程并非是独立线程,而是在主线程之内执行。具体来说,当你启动一个协程时,他会立即执行,但只是执行到第一个yield return之前,协程下次执行是在yield条件满足时。事实上,通过实验可以发现,如果仅仅是yield return null,协程的代码会在Update()执行完之后被执行,每次执行到下一个yield return null,再去执行Update()
如果理解协程并非多线程这件事后,你的问题就很好解释了。如果想在for循环中每一次延时,就要插入yield return的延时条件。将for所在方法作为协程启动就OK了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进