这是个热点案例。从某种意义上说,即使在建议中它也没有任何解释。
所以
我有场景中的立方体。
在循环中我为每个立方体启动协同程序,这个协程会做下一件事:
它将立方体的颜色从黑色(0,0,0)更改为红色(1,0,0),然后执行反转操作。在我的代码中,部分地,我将颜色从红色返回到黑色,我减少了G和B字段的值。我为什么要这么做?我会这样做,如果我在copypast之后修改这些行,我将颜色从黑色变为红色,当它不是红色时,以及当我改变R和G和B时。
private IEnumerator CororRoutine(Material cubeMaterial)
{
float coff = 1f;
while (cubeMaterial.color.r < 1.0f)
{
cubeMaterial.color = new Color(
cubeMaterial.color.r + coff * Time.deltaTime,
0.0f,
0.0f);
yield return new WaitForEndOfFrame();
}
while (cubeMaterial.color.r > 0.0f)
{
cubeMaterial.color = new Color(
cubeMaterial.color.r - coff * Time.deltaTime,
cubeMaterial.color.g - coff * Time.deltaTime,
cubeMaterial.color.b - coff * Time.deltaTime);
yield return new WaitForEndOfFrame();
}
}
正如您所看到的,已经双向改变的立方体有一点红色。但。材料中反照率颜色的值完全为(0,0,0)。 在屏幕截图中,您可以看到材料上的红色阴影。
如果你知道某些事情,那可以让我对这里发生的事情有所了解,这将非常有帮助。
问题是:当我减少已经为0的颜色通道时,为什么颜色会发生变化?这对任何人都知道吗? 我知道我不应该减少已经等于0的通道的值。 但是当我这样做的时候,当材料的颜色发生变化时,这似乎很奇怪。
答案 0 :(得分:1)
当我减少已经为0的颜色通道时,为什么颜色会发生变化? 这对任何人都知道吗?我知道我不应该减少值 已经等于0的频道。但是,这似乎很奇怪 当我这样做时,材料的颜色会发生变化。
ChristF和Le len已经回答了您的问题。请阅读它们。阅读他们谈到的负面价值。这就是问题所在。
我回答这个问题的唯一原因是因为我认为你做错了,而且这两个答案都没有提供一种改变颜色的正确方法。
放
Debug.Log("R: " + cubeMaterial.color.r);
Debug.Log("G: " + cubeMaterial.color.g);
Debug.Log("B: " + cubeMaterial.color.b);
在第二个while
循环中。您会注意到RGB值正在变为负值。我得到了以下值:
R: -0.0210881 G: -1.026095 B: -1.026095
color.r
,color.g
,color.b
和color.a
属性仅允许从0.0f
到1.0f
的值。您不能使用小于0f
的值或大于1f
的值。如果这样做,您将得到未定义的行为,因为没有人知道Unity如何处理超出此范围的值。不要问为什么,因为这是由Unity设定的规则。它是如此简单。
来自Unity Doc的直接引用:
这种结构在整个Unity中用于传递颜色。每 color component是一个浮点值,范围从0到1.
请注意,您当前的while循环无法阻止值低于0
或高于1
。
<强>解强>:
您有两种选择。
1 。您可以使用Mathf.Clamp
或Mathf.Clamp01
来解决此问题。这会将您的价值限制在0
和1
之间。
替换
cubeMaterial.color = new Color(
cubeMaterial.color.r - coff * Time.deltaTime,
cubeMaterial.color.g - coff * Time.deltaTime,
cubeMaterial.color.b - coff * Time.deltaTime);
带
cubeMaterial.color = new Color(
Mathf.Clamp(cubeMaterial.color.r - coff * Time.deltaTime, 0, 1),
Mathf.Clamp(cubeMaterial.color.g - coff * Time.deltaTime, 0, 1),
Mathf.Clamp(cubeMaterial.color.b - coff * Time.deltaTime, 0, 1));
2 。这是正确的方式。您不应该首先增加颜色值。这个答案中的第一个解决方案只是一个黑客攻击。真正的解决方案是使用Color.Lerp
。这将在两种颜色之间变化。我强烈推荐这个解决方案。
private IEnumerator CororRoutine(Material cubeMaterial)
{
float counter = 0f;
float changeDuration = 1f;
Color blackColor = Color.black; //OR new Color(0f,0f,1f);
Color redColor = Color.red; //OR new Color(1f,0f,0f);
//Black To Red
while (counter < changeDuration)
{
counter += Time.deltaTime;
cubeMaterial.color = Color.Lerp(blackColor, redColor, counter / changeDuration);
yield return new WaitForEndOfFrame();
}
counter = 0;
//Red To Black
while (counter < changeDuration)
{
counter += Time.deltaTime;
cubeMaterial.color = Color.Lerp(redColor, blackColor, counter / changeDuration);
yield return new WaitForEndOfFrame();
}
}
答案 1 :(得分:0)
也许是因为你在说
cubeMaterial.color.g - coff * Time.deltaTime,
cubeMaterial.color.b - coff * Time.deltaTime);
虽然已经0
答案 2 :(得分:0)
在我的代码中,部分地,我将颜色从红色返回到黑色,我减少了G和B字段的值。我为什么要这么做?我会这样做,如果我在copypast之后修改这些行,我将颜色从黑色变为红色,当它不是红色时,以及当我改变R和G和B时。
当您从其他地方复制代码时,您似乎忘了更改此代码。
如果您确定绿色和蓝色组件没有变化,那么您可以简单地写一下:
while (cubeMaterial.color.r > 0.0f)
{
cubeMaterial.color = new Color(
cubeMaterial.color.r - coff * Time.deltaTime,
0.0f,
0.0f);
yield return new WaitForEndOfFrame();
}
如果这些值可能已更改,那么您希望在递减其值之前检查绿色和蓝色成分是否已经为零。
如果coff - Time.deltaTime
的值大于当前cubeMaterial.color.r
,则可能会出现问题。这将导致&#34;否定&#34;颜色。即使成功创建,我也不知道。
如果没有创建,这将使您的对象保留最后的有效颜色 - 深红色。
如果它确实被创建,那么如果显示代码忽略了这个符号,这将解释对象的非常轻微的红色。
您正在使用float
值,虽然这些值非常适合速度,但它们存在准确性问题。当你足够接近时,我会添加一个额外的测试来将值设置为零:
float offset = coff * Time.deltaTime;
while (cubeMaterial.color.r > 0.0f)
{
cubeMaterial.color = new Color(
(offset > cubeMaterial.color.r) ? cubeMaterial.color.r - offset : 0.0f,
0.0f,
0.0f);
yield return new WaitForEndOfFrame();
}