I'm creating a scriptable object to store the color scheme for each level in my Brick Breaker game. There are a lot of options for how to input colors, but the way that TextMesh Pro does it for their Color Gradients is a great starting point. In their scriptable object (TMP > Scripts > Runtime > TMP_ColorGradient.cs), each row is a set of two colors, where each color can either be input using the color selector or by pasting in the hexidecimal value. When one of the fields is updated, the other field is updated automatically.

Sadly, the script file doesn't seem to contain the logic to recreate these input fields. I tried simply copying the file and renaming it, but the color format returns to the default ScriptableObject / SerializedField input style for Colors, namely without the text input option.

Does anyone know how to recreate TMP's input fields?

TextMesh Pro Scriptable Gradient Interface

In addition to Stack Exchange's Similar Questions step, here are all the searches I did looking for answers: Search 01 - "tmp color gradient input" unity color serializable how to connect two serializable variables in unity tmp color gradient file


1 Answer 1


There's a very similar example in the ColorUtility.TryParseHtmlString doc page.

The main idea is to have a single Color field that is drawn with a custom PropertyDrawer, so the value of both representations is always the same.

As for having two properties in the same row, I think EditorGUILayout.BeginHorizontal should do.

Edit to address the comment:

The empty class is just declaring an Attribute (the things that go in square brackets). It's empty because the attribute itself doesn't do anything, it's just a tag that you apply to an existing field or property. So far, we are just saying "the attribute ColorHtmlPropertyAttribute exists".

Then, something else can use reflection to check "hey, does this specific field have the attribute ColorHtmlPropertyAttribute?" and, if it does, it can treat that field in any special way it wants.

In this case, the thing making that check is the code responsible for drawing the inspector (which we did not write), so it's a bit more confusing, but also way easier. Instead of writing the reflection stuff ourselves, we are just telling the inspector to use the ColorHtmlPropertyDrawer on any field that is marked with ColorHtmlPropertyAttribute with the line:


And everything else is handled under the hood.

The last confusing thing about this whole attribute situation is that, in the example, the field is tagged [ColorHtmlProperty], rather than [ColorHtmlPropertyAttribute], which is the name that we declared. This is some prime C# nonsense for you, where if you declare an attribute whose name ends with "Attribute" you are actually allowed to skip that when using it, for some reason. I hate it :)

And as for why there are to assignment statements, it's just because the change can have ocurred in any of the two places in the inspector. If you picked a color, the new value comes directly from the EditorGUI.ColorField() call, but if you wrote the html string you have to take the return value of the EditorGUI.TextField() call and parse it.

  • \$\begingroup\$ The code doesn't look too complex, but I'm not really following the important parts. I don't know how to use Editor scripts yet either. Why are there three scripts? The shorter scripts are mostly empty, so I'm not really sure how to implement them. I'm assuming I don't need the Monobehavior class and can replace it with my Scriptable Object, but I can't see how "[ColorHtmlProperty]" connects to the drawer, how the two color fields are connected, or why "property.colorValue has two assignment statements at the end of ColorHtmlPropertyDrawer. \$\endgroup\$
    – MXMLLN
    Commented Feb 25, 2023 at 8:41
  • \$\begingroup\$ I can't seem to get this to work. The only important difference is that I'm using a ScriptableObject. Could that be a problem? I simply copied the code, adding that drawer into a new Editor directory under Assets > Scripts. What else could possibly go wrong? @PepeOjeda \$\endgroup\$
    – MXMLLN
    Commented Feb 26, 2023 at 9:07
  • 1
    \$\begingroup\$ I did a test and it seems to work fine with ScriptableObject. Is the color property showing like normal, or just not showing at all? Because, if it's not showing it's probably just that you are not serializing it (making it public or marking it with [SerializeField] as well as [ColorHtmlProperty]). \$\endgroup\$
    – PepeOjeda
    Commented Feb 26, 2023 at 14:38
  • \$\begingroup\$ For some reason, I didn't copy over the Editor qualifier (or whatever it's called): [CustomPropertyDrawer(typeof(ColorHtmlPropertyAttribute))] Thanks again for all the support! I'm up and running \$\endgroup\$
    – MXMLLN
    Commented Mar 2, 2023 at 8:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .