【发布时间】:2018-05-16 23:08:43
【问题描述】:
不完全确定如何表达标题,但我想每秒在一个对象上生成一种随机颜色。我还希望这种颜色与对象已有的旧颜色不相似。如果当前的随机颜色与对象已有的颜色相同,则再次重新生成随机颜色。该对象只是一个Text 组件。
这是我用来生成颜色的函数:
public Color genRandomColor()
{
float r, g, b;
r = UnityEngine.Random.Range(0f, 1f);
g = UnityEngine.Random.Range(0f, 1f);
b = UnityEngine.Random.Range(0f, 1f);
return new Color(r, g, b);
}
为了比较颜色是否相似,我移植并使用了this对C#的回答。
public double ColourDistance(Color32 c1, Color32 c2)
{
double rmean = (c1.r + c2.r) / 2;
int r = c1.r - c2.r;
int g = c1.g - c2.g;
int b = c1.b - c2.b;
double weightR = 2 + rmean / 256;
double weightG = 4.0;
double weightB = 2 + (255 - rmean) / 256;
return Math.Sqrt(weightR * r * r + weightG * g * g + weightB * b * b);
}
我将随机颜色生成器放在协程函数内的while 循环中,一遍又一遍地运行,直到生成的颜色不相似。每次生成随机颜色时,我都会使用yield return null; 等待一帧,这样它就不会冻结程序。
const float threshold = 400f;
bool keepRunning = true;
while (keepRunning)
{
Text text = obj.GetComponent<Text>();
//Generate new color but make sure it's not similar to the old one
Color randColor = genRandomColor();
while ((ColourDistance(text.color, randColor) <= threshold))
{
Debug.Log("Color not original. Generating a new Color next frame");
randColor = genRandomColor();
yield return null;
}
text.color = randColor;
yield return new WaitForSeconds(1f);
}
一切似乎都在解决一个小问题。
问题在于,有时需要1 到3 秒才能重新生成与旧颜色不同的颜色。我删除了yield return null; 以防止它等待每一帧,它现在似乎可以工作,但我冒着冻结整个游戏的风险,因为我现在使用随机函数来控制while 循环。我已经注意到微小的冻结,这并不好。
有什么更好的方法可以在不冻结游戏或等待几秒钟的情况下生成与对象的新颜色不相似的随机颜色?
【问题讨论】:
-
为什么不提前生成一个颜色数组并从中选择随机值呢?这应该可以节省一些运行时间...
-
我想过,但我不希望颜色是预先确定的或仅限于几种颜色。我只是希望随机颜色尽可能不同。
-
Zohar 说的一样。我不能在另一个线程中使用 Unity 的 API(随机)线程。虽然,我可以使用 C# 标准随机 API,但我试图避免使用存储在集合中的预定颜色。就像我的第一个回复一样,我希望颜色尽可能独特,而不是有时重复使用一些颜色。您的
Thread建议是个好主意,我会研究一下。 -
我没有很好地解释最后的评论。请记住,我不是在生成随机数。如果那是我正在做的事情,我会走这条路。我这样做是为了颜色。如果我必须预先填充它们,那么我更有可能在数组中看到相似的颜色,或者一遍又一遍地回收 HashSet。我想减少再次看到相同颜色的机会。
-
@mjwills 您的第一条评论给了我一个想法,即每次我需要同时使用 ThreadPool 生成多种颜色,然后选择与对象当前颜色不相似的颜色。这应该给我更多独特的颜色,然后预先填充颜色。