Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在不停止例程的情况下多次执行该例程?_C#_Unity3d_Ienumerator - Fatal编程技术网

C# 如何在不停止例程的情况下多次执行该例程?

C# 如何在不停止例程的情况下多次执行该例程?,c#,unity3d,ienumerator,C#,Unity3d,Ienumerator,我有一系列的游戏对象是灯光,我试图随着时间的推移增加和减少点光源的范围大小,问题是灯光有时并不会随着时间的推移而减少,它们只是立即变为范围0 using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class MainMenu : MonoBehaviour { public GameObject[]

我有一系列的游戏对象是灯光,我试图随着时间的推移增加和减少点光源的范围大小,问题是灯光有时并不会随着时间的推移而减少,它们只是立即变为范围0

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class MainMenu : MonoBehaviour
{
    public GameObject[] stars;

    private void Start()
    {
        StartCoroutine(ChooseStar());
    }

    public void PlayGame()
    {
        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
    }

    public void QuitGame()
    {
        Application.Quit();
    }


    IEnumerator IncreaseRadius(GameObject star, float duration)
    {
        Debug.Log("Increasing: "+star.name + " radius: " + star.GetComponent<Light>().range);
        float counter = 0;

        while (counter < duration)
        {
            counter += Time.deltaTime;
            star.GetComponent<Light>().range = counter;
            yield return null;
        }
        StartCoroutine(DecreaseRadius(star));
    }

    IEnumerator DecreaseRadius(GameObject star)
    {
        Debug.Log("Decreasing: "+star.name+" radius: "+ star.GetComponent<Light>().range);
        float counter = star.GetComponent<Light>().range;

        while (star.GetComponent<Light>().range >= 0f)
        {
            counter -= Time.deltaTime;
            star.GetComponent<Light>().range = counter;
            yield return null;
        }
        star.GetComponent<Light>().range = 0f;

    }

    IEnumerator ChooseStar()
    {
        float duration = Random.Range(3, 8);
        float waitTime = 2f;

        GameObject choosenStar = stars[Random.Range(0, stars.Length)];

        if (choosenStar.GetComponent<Light>().range <= 0f)
        {
            StartCoroutine(IncreaseRadius(stars[Random.Range(0, stars.Length)], duration));
        }
        else
        {
            waitTime = 0f;
        }

        yield return new WaitForSeconds(waitTime);
        StartCoroutine(ChooseStar());

    }
}
使用系统集合;
使用System.Collections.Generic;
使用UnityEngine;
使用UnityEngine.SceneManagement;
公共类主菜单:MonoBehavior
{
公众游戏对象[]明星;
私有void Start()
{
start例程(ChooseStar());
}
公共游戏
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex+1);
}
公共游戏()
{
Application.Quit();
}
IEnumerator递增半径(游戏对象星,浮动持续时间)
{
Log(“增加:“+star.name+”半径:“+star.GetComponent().range”);
浮点计数器=0;
while(计数器<持续时间)
{
计数器+=时间增量时间;
star.GetComponent().range=计数器;
收益返回空;
}
STARTCOUTION(减小半径(星形));
}
IEnumerator递减半径(游戏对象星)
{
Log(“递减:“+star.name+”半径:“+star.GetComponent().range”);
浮点计数器=star.GetComponent().range;
while(star.GetComponent().range>=0f)
{
计数器-=Time.deltaTime;
star.GetComponent().range=计数器;
收益返回空;
}
star.GetComponent().range=0f;
}
IEnumerator ChooseStar()
{
浮动持续时间=随机范围(3,8);
浮动等待时间=2f;
GameObject choosenStar=stars[随机范围(0,stars.Length)];

如果(选择senstar.GetComponent().range来回答一般问题:您只需将

while (true)
{
   ... 

   yield return ...
}
在你的代码周围。只要你
在它里面的某个地方产生
,这对协同程序是完全有效的


我猜你会得到并发的协同路由,因为你不会等到
IncreaseRadius
完成后再选择下一个随机星…这可能和以前一样

if (chosenStar.range <= 0f)
{
    StartCoroutine(IncreaseRadius(stars[Random.Range(0, stars.Length)], duration));
}
else
{
    waitTime = 0f;
}
参照对象的方式与以前相同,但现在您直接处理的是
灯光
参照,而不是
游戏对象

那你知道吗

float duration = Random.Range(3, 8);
实际上,返回介于
3
7
之间的随机完整
int
值。如果您希望
float
值也介于
3
8
之间,那么还应包括例如
3.253453f
,那么您应该使用

var duration = Random.Range(3.0f, 8.0f);
解决方案1-一次仅一颗星 作为一个简单的替代方案,您每次只能制作一个星星的动画。您可以通过
生成返回
另一个
IEnumerator
来实现这一点。这会使另一个
IEnumerator
执行,同时等待它完成。例如

public Light[] stars;

private void Start()
{
    StartCoroutine(ChooseStar());
}

private IEnumerator IncreaseRadius(Light star, float duration)
{
    Debug.Log("Increasing: " + star.name + " radius: " + star.range);
    float counter = 0;

    while (counter < duration)
    {
        counter += Time.deltaTime;
        star.range = counter;
        yield return null;
    }

    // again do the decreasing and at the same time wait for it to finish
    yield return DecreaseRadius(star);
}

private static IEnumerator DecreaseRadius(Light star)
{
    Debug.Log("Decreasing: " + star.name + " radius: " + star.range);
    var counter = star.range;

    while (star.range >= 0f)
    {
        counter -= Time.deltaTime;
        star.range = counter;
        yield return null;
    }
    star.range = 0f;
}

IEnumerator ChooseStar()
{
    // Looks scary but is totally fine in Coroutines as long as you yield somewhere
    // instead of starting a new Coroutine simple continue the one you already have
    while (true)
    {
        var duration = Random.Range(3.0f, 8.0f);

        var choosenStar = stars[Random.Range(0, stars.Length)];

        // This starts the Increase routine on that star
        // and at the same time waits for it to finish!
        //
        // since we also wait until DecreaseRadius is done this means 
        // at any time only exactly 1 star is animated at the same time
        yield return IncreaseRadius(choosenStar, duration);
    }
}
public Light[] stars;

// Use a list for dynamically adding and removing items
private List<Light> availableStars = new List<Light>();

private void Start()
{
    // initialize the available list
    // copy the references from stars
    availableStars.AddRange(stars);

    StartCoroutine(ChooseStar());
}

private IEnumerator IncreaseRadius(Light star, float duration)
{
    Debug.Log("Increasing: " + star.name + " radius: " + star.range);

    // As soon as you start animating this star
    // remove it from the list of availables
    availableStars.Remove(star);

    float counter = 0;

    while (counter < duration)
    {
        counter += Time.deltaTime;
        star.range = counter;
        yield return null;
    }

    // Decreasing and at the same time wait for it to finish
    yield return DecreaseRadius(star);

    // when finished add the star again to the availables
    availableStars.Add(star);
}

private static IEnumerator DecreaseRadius(Light star)
{
    Debug.Log("Decreasing: " + star.name + " radius: " + star.range);
    var counter = star.range;

    while (star.range >= 0f)
    {
        counter -= Time.deltaTime;
        star.range = counter;
        yield return null;
    }
    star.range = 0f;
}

IEnumerator ChooseStar()
{
    // Looks scary but is totally fine in Coroutines as long as you yield somewhere
    while (true)
    {
        var duration = Random.Range(3.0f, 8.0f);

        // in case that currently all stars are being animated
        // simply wait until the next one becomes available again
        yield return new WaitUntil(() => availableStars.Count > 0);

        // Pick a random star from the availables instead
        var chosenStar = availableStars[Random.Range(0, availableStars.Count)];

        // this check becomes then actually redundant
        //if (chosenStar.range <= 0f)
        //{
        StartCoroutine(IncreaseRadius(chosenStar, duration));
        yield return new WaitForSeconds(2f);
        //}
    }
}
public Light[]星星;
私有void Start()
{
start例程(ChooseStar());
}
专用IEnumerator递增半径(亮星、浮动持续时间)
{
调试日志(“增加:“+star.name+”半径:“+star.range”);
浮点计数器=0;
while(计数器<持续时间)
{
计数器+=时间增量时间;
star.range=计数器;
收益返回空;
}
//再次进行递减,同时等待它完成
收益率递减半径(星形);
}
专用静态IEnumerator递减半径(亮星)
{
调试日志(“减小:“+star.name+”半径:“+star.range”);
var计数器=星型范围;
而(星形范围>=0f)
{
计数器-=Time.deltaTime;
star.range=计数器;
收益返回空;
}
star.range=0f;
}
IEnumerator ChooseStar()
{
//看起来很吓人,但只要你在某个地方让步,在合作中是完全可以的
//不要开始一个新的协同程序,而是继续你已经拥有的
while(true)
{
var持续时间=随机范围(3.0华氏度,8.0华氏度);
var choosenStar=星星[随机范围(0,星星长度)];
//这将启动该星上的递增例程
//同时等待它完成!
//
//因为我们也要等到半径减小,这意味着
//在任何时候,只有一颗星同时被设置动画
收益率增加半径(choosenStar,持续时间);
}
}

解决方案2-过滤随机数据 或者,如果您希望允许对星星进行并行动画,我只需过滤掉可用星星(当前未设置动画的星星)列表即可获得随机范围

public Light[] stars;

private void Start()
{
    StartCoroutine(ChooseStar());
}

private IEnumerator IncreaseRadius(Light star, float duration)
{
    Debug.Log("Increasing: " + star.name + " radius: " + star.range);
    float counter = 0;

    while (counter < duration)
    {
        counter += Time.deltaTime;
        star.range = counter;
        yield return null;
    }

    // again do the decreasing and at the same time wait for it to finish
    yield return DecreaseRadius(star);
}

private static IEnumerator DecreaseRadius(Light star)
{
    Debug.Log("Decreasing: " + star.name + " radius: " + star.range);
    var counter = star.range;

    while (star.range >= 0f)
    {
        counter -= Time.deltaTime;
        star.range = counter;
        yield return null;
    }
    star.range = 0f;
}

IEnumerator ChooseStar()
{
    // Looks scary but is totally fine in Coroutines as long as you yield somewhere
    // instead of starting a new Coroutine simple continue the one you already have
    while (true)
    {
        var duration = Random.Range(3.0f, 8.0f);

        var choosenStar = stars[Random.Range(0, stars.Length)];

        // This starts the Increase routine on that star
        // and at the same time waits for it to finish!
        //
        // since we also wait until DecreaseRadius is done this means 
        // at any time only exactly 1 star is animated at the same time
        yield return IncreaseRadius(choosenStar, duration);
    }
}
public Light[] stars;

// Use a list for dynamically adding and removing items
private List<Light> availableStars = new List<Light>();

private void Start()
{
    // initialize the available list
    // copy the references from stars
    availableStars.AddRange(stars);

    StartCoroutine(ChooseStar());
}

private IEnumerator IncreaseRadius(Light star, float duration)
{
    Debug.Log("Increasing: " + star.name + " radius: " + star.range);

    // As soon as you start animating this star
    // remove it from the list of availables
    availableStars.Remove(star);

    float counter = 0;

    while (counter < duration)
    {
        counter += Time.deltaTime;
        star.range = counter;
        yield return null;
    }

    // Decreasing and at the same time wait for it to finish
    yield return DecreaseRadius(star);

    // when finished add the star again to the availables
    availableStars.Add(star);
}

private static IEnumerator DecreaseRadius(Light star)
{
    Debug.Log("Decreasing: " + star.name + " radius: " + star.range);
    var counter = star.range;

    while (star.range >= 0f)
    {
        counter -= Time.deltaTime;
        star.range = counter;
        yield return null;
    }
    star.range = 0f;
}

IEnumerator ChooseStar()
{
    // Looks scary but is totally fine in Coroutines as long as you yield somewhere
    while (true)
    {
        var duration = Random.Range(3.0f, 8.0f);

        // in case that currently all stars are being animated
        // simply wait until the next one becomes available again
        yield return new WaitUntil(() => availableStars.Count > 0);

        // Pick a random star from the availables instead
        var chosenStar = availableStars[Random.Range(0, availableStars.Count)];

        // this check becomes then actually redundant
        //if (chosenStar.range <= 0f)
        //{
        StartCoroutine(IncreaseRadius(chosenStar, duration));
        yield return new WaitForSeconds(2f);
        //}
    }
}
public Light[]星星;
//使用列表动态添加和删除项目
private List availableStars=新列表();
私有void Start()
{
//初始化可用列表
//从星星复制引用
可用星。添加范围(星);
start例程(ChooseStar());
}
专用IEnumerator递增半径(亮星、浮动持续时间)
{
调试日志(“增加:“+star.name+”半径:“+star.range”);
//一旦你开始为这颗星制作动画
//将其从可用列表中删除
可用状态。移除(星形);
浮点计数器=0;
while(计数器<持续时间)
{
计数器+=时间增量时间;
star.range=计数器;
收益返回空;
}
//减少,同时等待它完成
收益率递减半径(星形);
//完成后,再次将星号添加到可用星号
可用状态。添加(星号);
}
专用静态IEnumerator递减半径(亮星)
{
调试日志(“减小:“+star.name+”半径:“+star.range”);
var计数器=星型范围;
而(星形范围>=0f)
{
计数器-=Time.deltaTime;
star.range=计数器;
收益返回空;
}
star.range=0f;
}
IEnumerator ChooseStar()
{
//看起来很吓人,但很彻底