我可以使用IEnumerator作为更新功能吗?

时间:2019-08-17 07:11:04

标签: c# unity3d

我有一些结构,例如object-4 child object-在每个孩子中还有2个孩子。我想为每个子对象更改其颜色的alpha。

我创建了应该更改Alpha的IEnumarator,但是当我对其进行测试时,它仅更改为0.8,而不是0,并且我还想按时间更改它,例如平稳地更改2秒钟,但是它发生得很快

imageComponents = gameObject.GetComponentsInChildren<Image>();
textComponents = gameObject.GetComponentsInChildren<Text>();    

IEnumerator HideAllBoosters(Transform _object)
    {
        foreach (Image image in imageComponents)
        {
            Color _color = image.GetComponent<Image>().color;
            _color = new Color(_color.r, _color.g, _color.b, 0);
            image.GetComponent<Image>().color = Color.Lerp(image.color, _color, 10 * Time.deltaTime);
        }
        foreach (Text text in textComponents)
        {
            Color _color = text.GetComponent<Text>().color;
            _color = new Color(_color.r, _color.g, _color.b, 0);
            text.GetComponent<Text>().color = Color.Lerp(text.color, _color, 10 * Time.deltaTime);
        }
        yield return null;
    } 

Idk如何正确执行操作,mb我应该在Update中为每个对象更改颜色,但是我不确定它对于清晰易懂的代码有好处,所以我要问的是-我可以为每个对象使用另一个IEnumerator来工作吗更新,例如:

    foreach (Image image in imageComponents)
    {
         StartCourutine(changeAlpha(image));
    }

1 个答案:

答案 0 :(得分:1)

错误在于传递10 * Time.deltaTime作为t的{​​{1}}值

如果您查看Lerp(Vector3 a, Vector3 b, float t);的{​​{3}}:

  

当t = 0时返回a。当t = 1时返回b。当t = 0.5时,返回a和b之间的中间点。

这意味着,为了使Alpha具有良好的淡入淡出效果,Lerp()的{​​{1}}值应为1到0(如果要淡入淡出则为0到1)在一定时间内。目前,您要传入的t始终是相同的值(基于帧速率)。 (在这种情况下,约为0.8)。

要解决此问题,您需要将Lerp()设为在0到1之间缓慢增加/减少(取决于您要淡入还是淡出的值)的值。一种实现方法是将逻辑包裹在while循环中。

10 * Time.deltaTime

每次循环运行时,这将使t的值增加float speed = 0.01f; float time = 0; while ( time < 1) { time += speed; //Rest of code } (在本例中为0.01),在本例中为100次迭代(0.01 * 100 = 1)。

我们现在可以将此time值用作speed方法中的time值,以使其平滑过渡

t

如果您希望淡入淡出花费更多或更少的时间,只需增加或减少Lerp()中的值即可。

整个实现看起来像这样(请注意,我也做了一些优化,稍后将介绍)

image.color = Color.Lerp(image.color, _color, time);

我完成的优化: 您通过speedpublic float speed = 0.01f; //The speed at which the fade happens private Image[] imageComponents; private Text[] textComponents; void Start() { imageComponents = gameObject.GetComponentsInChildren<Image>(); //Cache the images so we don't have to find them every time textComponents = gameObject.GetComponentsInChildren<Text>(); //Cache the texts StartCoroutine(HideAllBoosters());//Start the Coroutine } IEnumerator HideAllBoosters() { float t = 0; //Start value for our loop while (t < 1) // 1 indicates the max value of t at which the loop stops. In this case after 100 iterations since the speed is 0.01 { t += speed; foreach (Image image in imageComponents) { Color _color = image.color; _color = new Color(_color.r, _color.g, _color.b, 0); image.color = Color.Lerp(image.color, _color, t); //t dictates how far in the interpolation we are. } foreach (Text text in textComponents) { Color _color = text.color; _color = new Color(_color.r, _color.g, _color.b, 0); text.color = Color.Lerp(text.color, _color, t); } yield return null; } } 循环的数组已经是imageComponentstextComponents类型。这意味着当您在Image循环中遍历它们时,Textforeach()已经属于它们各自的类型,并且已经拥有对其组成部分的引用。这意味着您的Image imageText text呼叫是不必要的。

例如:

.GetComponent<Image>()

相同
.GetComponent<Text>()

我还删除了Color _color = image.GetComponent<Image>().color; 所需的Color _color = image.color; 参数,因为该方法似乎根本没有使用该参数。可能是您稍后在此问题范围之外的函数中确实使用了该值。如果是这种情况,则需要将其包括在内。