c# - 我可以使用 IEnumerator 作为更新函数吗?
问题描述
我有一些结构,如对象 - 4 个子对象 - 每个孩子还有 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,它可以像 Update 一样工作,之类的:
foreach (Image image in imageComponents)
{
StartCourutine(changeAlpha(image));
}
解决方案
错误是10 * Time.deltaTime
作为t
值传递Lerp(Vector3 a, Vector3 b, float t);
如果您查看以下文档Lerp()
:
当 t = 0 时返回 a。当 t = 1 时返回 b。当 t = 0.5 时,返回 a 和 b 之间的中间点。
这意味着为了让您的 alpha 具有良好的淡入淡出效果, 的t
值Lerp()
应该是一个在一定时间内从 1 到 0(或者如果您想淡入,则为 0 到 1)的值。现在10 * Time.deltaTime
,根据帧速率,您传入的值将始终相同。(在这种情况下,大约为 0.8)。
要解决此问题,您需要t
一个在 0 和 1 之间缓慢增加/减少(取决于您想要淡入还是淡出)的值。一种方法是将您的逻辑封装在一个while循环中。
float speed = 0.01f;
float time = 0;
while ( time < 1)
{
time += speed;
//Rest of code
}
这将在每次循环运行时将time
值增加(在本例中为 0.01),在本例中为 100 次迭代(0.01 * 100 = 1)。speed
我们现在可以将此time
值应用为方法中的t
值,Lerp()
以使其平滑过渡
image.color = Color.Lerp(image.color, _color, time);
如果您希望淡入淡出花费更多或更少的时间,只需增加或减少 中的值即可speed
。
整个实现看起来像这样(请注意,我还做了一些优化,稍后会介绍)
public 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;
}
}
我所做的优化:您循环遍历的数组已经是imageComponents
and类型。这意味着当您在循环中遍历它们并且已经是它们各自的类型时,并且已经持有对其组件的引用。这意味着您的和电话是不必要的。textComponents
Image
Text
foreach()
Image image
Text text
.GetComponent<Image>()
.GetComponent<Text>()
例如:
Color _color = image.GetComponent<Image>().color;
是相同的
Color _color = image.color;
我还删除了所需的Transform _object
参数HideAllBoosters
,因为该方法似乎根本没有使用它。可能是您稍后在此问题范围之外的函数中的某处使用了此值。如果是这种情况,您当然需要将其包括在内。
推荐阅读
- excel - 如何使用 VBA 编辑具有特定条件的表格?
- html - 表单未读取要提交的输入
- html - 如何使用 CSS 覆盖包含元素的内联样式?
- c# - NullReferenceException:对象引用未设置为对象 PlayerMovement.Update () 的实例
- javascript - 如何使用jQuery获取在data-*中找到的特定值的第一个实例
- ios - 如何使用 RevenueCat 购买耗材?
- javascript - 嵌入的 PDF 在 chrome 和 safari 中呈现为空白
- html - 设置最小高度等于内容高度
- docker - 如何将 docker-compose 中的变量用作多个服务的命名卷?
- python - 如何对多个列上的数据集进行分组并同时进行不同的聚合?Python