So, here’s a basic example that may work. I have not tested all possible values of color channels, but I tested each channel, not a number, positive and negative infinity, alpha etc, to make sure the output stays within #000000 to #FFFFFF and doesn’t throw exceptions. You may wish different behaviour for negative, positive infinity or not a number cases perhaps, but this is up to what makes sense to you. In most cases, you won’t be feeding those values into any channel anyway.
using UnityEngine;
public static class ColorTypeConverter
{
public static string ToRGBHex(Color c)
{
return string.Format("#{0:X2}{1:X2}{2:X2}", ToByte(c.r), ToByte(c.g), ToByte(c.b));
}
private static byte ToByte(float f)
{
f = Mathf.Clamp01(f);
return (byte)(f * 255);
}
}
And the tests for reference.
using NUnit.Framework;
using UnityEngine;
[TestFixture]
[Category("Type Conversion")]
internal class ColorTypeConverterTests
{
[Test]
public void ConvertsCommonColors()
{
Assert.AreEqual("#000000", ColorTypeConverter.ToRGBHex(Color.black));
Assert.AreEqual("#FFFFFF", ColorTypeConverter.ToRGBHex(Color.white));
}
[Test]
public void IgnoresAlphaChannel()
{
Assert.AreEqual("#FFFFFF", ColorTypeConverter.ToRGBHex(new Color(1, 1, 1, 0)));
Assert.AreEqual("#FFFFFF", ColorTypeConverter.ToRGBHex(new Color(1, 1, 1, 1)));
}
[Test]
public void ConvertsChannelsInRGBOrder()
{
Assert.AreEqual("#FF0000", ColorTypeConverter.ToRGBHex(Color.red));
Assert.AreEqual("#00FF00", ColorTypeConverter.ToRGBHex(Color.green));
Assert.AreEqual("#0000FF", ColorTypeConverter.ToRGBHex(Color.blue));
}
[Test]
public void ConvertsYellow()
{
UnityYellowIsKnown();
Assert.AreEqual("#FFEB04", ColorTypeConverter.ToRGBHex(Color.yellow));
}
[Test]
public void UnityYellowIsKnown()
{
// ConvertsYellow use yellow color. If Unity changes the definition of
// yellow, those tests will fail. To spare developer confusion about
// failing tests, assert that the channels are known. Because the channels
// are so arbitrary, it's also nice to see the floats in plain text.
Assert.AreEqual(1, Color.yellow.r, "Color.yellow.r changed");
Assert.AreEqual(0.921568632f, Color.yellow.g, "Color.yellow.g changed");
Assert.AreEqual(0.0156862754f, Color.yellow.b, "Color.yellow.b changed");
}
[Test]
public void ClampsChannelsBetweenZeroAndOne()
{
Assert.AreEqual("#FFFFFF", ColorTypeConverter.ToRGBHex(PosInf()));
Assert.AreEqual("#FFFFFF", ColorTypeConverter.ToRGBHex(Fill(1.5f)));
Assert.AreEqual("#FFFFFF", ColorTypeConverter.ToRGBHex(Fill(1)));
Assert.AreEqual("#000000", ColorTypeConverter.ToRGBHex(Fill(0)));
Assert.AreEqual("#000000", ColorTypeConverter.ToRGBHex(Fill(-0.5f)));
Assert.AreEqual("#000000", ColorTypeConverter.ToRGBHex(NegInf()));
}
[Test]
public void NotANumberConvertsToBlack()
{
Assert.AreEqual("#000000", ColorTypeConverter.ToRGBHex(NaN()));
}
private static Color NaN()
{
return Fill(float.NaN);
}
private static Color NegInf()
{
return Fill(float.NegativeInfinity);
}
private static Color PosInf()
{
return Fill(float.PositiveInfinity);
}
private static Color Fill(float c)
{
return new Color(c, c, c, c);
}
}