C# 如何在不停止例程的情况下多次执行该例程?
我有一系列的游戏对象是灯光,我试图随着时间的推移增加和减少点光源的范围大小,问题是灯光有时并不会随着时间的推移而减少,它们只是立即变为范围0C# 如何在不停止例程的情况下多次执行该例程?,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[]
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()
{
//看起来很吓人,但很彻底