Color3 comparision to BrickColor.Color is sometimes failing

(note: I’m new to these forums; I might have missed something here)

Right now, I am trying to achieve a color-picking system that compares selected RGB colors to BrickColor values and do one of the following in the comparision:

  • If it is the same color, output the BrickColor name
  • If not, then output it’s RGB components as the color name

The check is done in the scripts in the menu using this line of code:

if BrickColor.new(temporaryColor3Value).Color == Color3.new( 
    math.clamp(math.floor(temporaryColor3Value.r), 0, 1), 
    math.clamp(math.floor(temporaryColor3Value.g), 0, 1), 
    math.clamp(math.floor(temporaryColor3Value.b), 0, 1)) then

Obviously it’s not called temporaryColor3Value in the real script. The value is stored in a Color3Value untill the player is ready to choose their color and use it. The check in the scripts is the only thing that is not properly working. Everything else in the scripts is fine.

The issue is that sometimes this check fails to work for certain BrickColors, such as Bright red. What I noticed is that it’s comparing two numbers very close to each other that aren’t actually the same number (they’re supposed to be, but I guess a rounding error is causing it) as seen by outputing values in the command bar:

    > print(BrickColor.Red().Color)
    0.768628, 0.156863, 0.109804
    > print(Color3.fromRGB(196,40,28))
    0.768627, 0.156863, 0.109804
    > print(BrickColor.Red().Color == Color3.fromRGB(196,40,28))
    false

looking at the red value, it’s a difference of one number (8 to 7) that is causing the check to fail, and not properly display the name “Bright red” for that color, instead displaying “196, 40, 28.” Notably it doesn’t do this with colors who have all of their RGB components divisible by 255 into a rational number like Dark Taupe, which has it’s name properly displayed.

It seems to work for some colors and seems to not for others. CGA brown, Alder, Earth green, Deep blue, and Really black all can properly pass the check, while things like Dark green, Institutional white, Navy blue, Reddish brown, and Brick yellow fail to make it through the check when the Color3 has it’s values inserted. The script never errors at any point.

I attempted using HSV conversion to fix this like:

if Color3.toHSV(BrickColor.new(temporaryColor3Value).Color) == Color3.ToHSV(
    Color3.new(math.clamp(math.floor(temporaryColor3Value.r), 0, 1), 
    math.clamp(math.floor(temporaryColor3Value.g), 0, 1), 
    math.clamp(math.floor(temporaryColor3Value.b), 0, 1))) then

but it only fixes some colors, like Dark Green works now, but Bright red still fails to go through:

    > print(Color3.toHSV(BrickColor.Red().Color))
    0.01190475653857 0.85714286565781 0.76862752437592
    > print(Color3.toHSV(Color3.fromRGB(196,40,28)))
    0.011904766783118 0.85714286565781 0.76862746477127
    > print(Color3.toHSV(BrickColor.Red().Color) == Color3.toHSV(Color3.fromRGB(196,40,28)))
    false

In addition, that check also allows some RGB colors to falsely pass as an existing color. An example happens with the color Permission. I can have RGB values of 222, 89, 89 and have the check think that color is Permission, even though it’s actual color is 255, 89, 89. The output for those two is here:

    > print(Color3.toHSV(BrickColor.new("Persimmon").Color))
    1 0.65098035335541 1
    > print(Color3.toHSV(Color3.fromRGB(222,89,89)))
    1 0.59909909963608 0.87058824300766
    > print(Color3.toHSV(BrickColor.new("Persimmon").Color) == Color3.toHSV(Color3.fromRGB(222,89,89)))
    true

I have not tried other methods yet nor have been able to find anything of this sort on the forum, Though it might be because i’m doing something wrong with the line of code (Hopefully.)

1 Like

Convert those decimal values to discrete values from 0-255 and then compare those instead.

3 Likes

I decided to go and try that, but it still has that issue. Here’s the values as shown by the command bar:

    > print(BrickColor.Red().Color.r*255,BrickColor.Red().Color.g*255,BrickColor.Red().Color.b*255)
    196.00001871586 40.00000141561 28.000002130866
    > print(Color3.fromRGB(196,40,28).r*255,Color3.fromRGB(196,40,28).g*255,Color3.fromRGB(196,40,28).b*255)
    196.00000351667 40.00000141561 28.000000230968
    > print(Color3.fromRGB(196,40,28).r*255 == BrickColor.Red().Color.r*255)
    false
    > print(Color3.fromRGB(196,40,28).g*255 == BrickColor.Red().Color.g*255)
    true
    > print(Color3.fromRGB(196,40,28).b*255 == BrickColor.Red().Color.b*255)
    false

Though I notably could use math.floor() on them now. That might do it.

Edit: yep that solved it. Thanks for the input!

1 Like

floating-point errors will make numbers that are extremely close unequal to each other. Even changing OSes will change the 5th or 6th decimal of color3’s, which is enough to make numbers unequal. There always needs to be some normalizing aspect when comparing float equality or floats (in a game environment) will never be equal. In your case, you’ve normalized the float to multiples of 1.

1 Like

In case it’s useful, you can select the BrickColor nearest to a Color3 by passing it to BrickColor.new:

local bc = BrickColor.new(Color3.new(1, 0.5, 0))
print(bc.Name) --> Deep orange
print(bc.Color) --> 1, 0.686275, 0
3 Likes

This also works if you pass the RGB values to BrickColor.new alone.

local bc = BrickColor.new(1, 0.5, 0)
print(bc.Name) --> Deep orange
print(bc.Color) --> 1, 0.686275, 0