为什么当淡出 material 列表时,每个 material 都会在另一时间淡出,而不是所有 material 都同时淡出?

Why when fading out list of materials each material fade out in another time and not all the materials fade at the same time?

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class FadeInOut : MonoBehaviour
{
    List<Material> mats = new List<Material>();

    private void Start()
    {
        foreach (Transform g in transform.GetComponentsInChildren<Transform>())
        {
            if (g.GetComponent<SkinnedMeshRenderer>() != null)
            {
                var l = g.GetComponent<SkinnedMeshRenderer>().sharedMaterials.ToList();
                foreach(Material mat in l)
                {
                    mats.Add(mat);
                }                
            }
        }  
    }

    private void Update()
    {
        if(Input.GetKeyDown(KeyCode.G))
        {
            StartCoroutine(FadeTo(mats, 0, 0.5f));
        }
    }

    IEnumerator FadeTo(List<Material> materials, float targetOpacity, float duration)
    {
        for (int i = 0; i < materials.Count; i++)
        {
            Color color = materials[i].color;
            float startOpacity = color.a;

            float t = 0;

            while (t < duration)
            {
                t += Time.deltaTime;
                float blend = Mathf.Clamp01(t / duration);

                color.a = Mathf.Lerp(startOpacity, targetOpacity, blend);

                materials[i].color = color;

                yield return null;
            }
        }
    }
}

第一个 material 在 0.5f 秒后淡出,然后其他 materials 每个都在更长的时间内淡出,最后一个在第一个之后几乎 1-2 秒。

我希望所有 materials 同时淡出,如果时间是 0.5f 或 5f 然后在 5 秒后或 0.5f 之后淡出所有 materials 但是同时而不是一个接一个。

因为你的外部 for 循环正在经历 materials:

for (int i = 0; i < materials.Count; i++)

并且您的内部 while 循环正在 运行 将时间安排在一个 material:

while (t < duration)
{
    t += Time.deltaTime;
    // ...
    materials[i].color = color;
}

所以你得到 material 0,然后淡化它,然后你得到 material 1,然后淡化它,等等

如果你想将所有 materials 一起淡化,那么你应该交换你的循环,这样你就可以 运行 为所有内容设置一个计时器,然后在每个时间步迭代 materials , 比如:

IEnumerator FadeTo(List<Material> materials, float targetOpacity, float duration)
{
    float t = 0;
    List<float> startOpacities = new List<float>();
    foreach(var material in materials)
    {
        startOpacities.Add(material.color.a);
    }
    
    while (t < duration)
    {
        t += Time.deltaTime;
        float blend = Mathf.Clamp01(t / duration);
        
        for (int i = 0; i < materials.Count; i++)
        {
            Color color = materials[i].color;
            color.a = Mathf.Lerp(startOpacities[i], targetOpacity, blend);
            materials[i].color = color;
        }
        yield return null;
    }
}

所以我在这里缓存所有开始的不透明度,然后进入计时循环。每个定时循环我们增加 t 值,用于确定 blend,然后我们循环每个 material 并改变 alpha 通道。在设置完所有 material 之后,然后我们 yield return null.