How to use a custom UI material with TMP?

Hello,

I have a problem I’m trying to solve with TextMesh Pro and I cannot seem to figure out how to do it.

I have a UI material that I use for many elements of my UI. I would like to use that material for the surface of text and icons drawn with TextMesh Pro. I am unable to figure out how to do that.

The closest I’ve come was setting my TextMesh Pro object as a mask and then creating an image as a child object. The image can then have the material attached to it.

This works fine until I try to embed an icon in my text. The icon creates a “sub mesh” which doesn’t intersect with the text part of the TMP object and doesn’t contribute to the shape of the mask.

So I end up with regular text and empty spaces where the icons should be.

I feel like I’m going about this the wrong way.

What I want is text with an embedded icon painted with a single material.

What is the best way to accomplish this with TextMesh Pro?

Why are you trying to use a custom UI Material? Are you trying to do this to reduce the # of draw calls from 2 to 1?

Sub Mesh objects are created whenever more than one material is required to render the text object. The font asset assigned to the text object contains a child atlas texture that contains the glyphs for each character and a material that references this texture. The icons themselves could come from another font asset or sprite asset where another atlas texture and material is used.

Whether a text object used more than one material, clipping and masking should still work as expected.

No. I couldn’t care less about draw calls. They have no impact on the performance of my current game.

I have a material that was hard for me to make. I have text for a “buy” button in which I wanted to embed the symbol for in-game currency.

Both the text and the icon must match exactly the look and feel of the rest of the UI.

Here is what it looks like when I did my own layout.

6139698--669948--upload_2020-7-27_18-39-37.png

That’s certainly what I expected. It’s just not what actually happened.

What version of the TMP package are you using?

What is the font file you are using?

Are the icons from a separate font file or some atlas texture?

Where is the frame around the text / icon coming from? Another texture?

How is the clipping / masking not working?

Can you provide me with a simple scene for me to look at?

VersionIVersion 3.0.0.using

I’m using the stock font file that gets imported when you start using TMP.

The icons are from a sprite sheet I packed using an asset store asset. I looked to it in the other thread (the one about using sprite atlases).

There’s no problem with clipping the text. It’s using the text to clip something else that is the problem.

I’m trying to use a TextMesh Pro object as a mask and then creating an image as a child object. Only the text part is used to clip the child image. Since the mask never includes the embedded images, those parts of the image are never shown, creating the effect of the images never appearing.

The masking is not working in that the submesh is not included as part of the “on” portion of the mask.

Yes. This would be very easy to reproduce with the steps I’ve outlined. I will make a project for you.

Did you create a sprite asset to contain these icons so that you can inline both with the text?

Please test with version 3.0.1 of the TMP package which was released yesterday as it contains improvement to the handling of masking.

Here is the sample project. I did the TextMesh Pro part using nothing but out of the box TMP assets that get imported when you click that like “import essentials” helper button.

6139905–669984–NoCheese.zip (1.27 MB)

The .zip is for 2019.3 but I initially reproduced this in 2020.1. I’m not sure it’s a TMP thing at all. I decompiled the Mask class and I saw no evidence that it had a concept of a sub-mesh.

3.0.1 makes no difference in my sample.

Thank you for providing the sample. I will take a closer look later tonight and follow up shortly there after.

I just had a chance to take a look at the project you provide and indeed the Mask component only uses a single Graphic component as a masking source.

I’ll further explore this tomorrow to see if it might be possible to modify the Mask component to use multiple Graphic as the masking source.

In the meantime, it would be possible to create a custom font file and to include in such font file, the icons that you need. The idea would to inject these icons in the custom Unicode range which is 0xE000 - 0xF8FF.

You could use a free tool like IcoMoon where you could import your source icons (SVG) and create a font file with those. Then you would use some font editing tool like FontForge or Font Creator to add / copy / paste these new glyphs and character to an existing font file.

In this example, I added the Connection icon from IcoMoon (E91B) to the following font file using Font Creator.

6140142--670056--upload_2020-7-27_22-14-12.png

I then saved and imported this custom font file in Unity and create a font asset from it. I then assigned it to a text object with a Mask component and referenced this icon using \uE91B.

6140142--670059--upload_2020-7-27_22-16-46.png

I have custom shader and when i returned to my old project i’m getting errors at these because shader doesn’t have that property. And unity rechecks it even i change codes in your package.

Back to the original topic …

You are trying to use a Mask to expose a custom texture behind it to achieve the visual FX in the 3rd post. Correct?

What if we could come close using 2 text objects. First we would create new font asset with a larger sampling point size to padding ratio (25%) to get us extra range for our underlay.

We would then create a new material preset for our background with Face Color fully transparent, Underlay with large Dilation and max softness.

Then our top text object would just use the default material with vertex color (Yellow).

Then combined we would get the following

Changes to packages have to be done in the Global Cache or you need to embed the package otherwise upon closing Unity, the changes will be reset.

In terms of the errors above, those are all the SDF related properties which your custom shader may not have. I don’t know if your custom shader is derived from the SDF shaders included in TMP or one something else not using SDF.

If your font asset is an SDF font asset, then TMP would expect the shader to have those SDF related properties.

If you want to continue to use SDF, you should consider basing your custom shader on one of the TMP shaders like the Mobile Distance Field or the full Distance Field shader

I have modified your Mobile Distance Field to Urp shader with deleting a lot properties and optimized. Is there anyway to override it basically? Do you have git repos for this package? What i don’t like in your work is that you don’t let it customizable. You did lots of great things. But really its restriction is too high and i can’t use it with my way and too complicated for me.

That’s very close to what I’m already doing to generate the image in my third post. I use a horizontal layout, a text object, and an image object. The image object has an aspect-ratio-controlled layout element fixing it’s minimum and preferred sizes too request an aspect ratio of 3:4. That contains the icon. The text box is set to auto size. The image has a layout priority of 1000000. The layout is set to control height and width but only to force expand height. The layout is set to middle center its content.

This works fine for the very simple case of a buy button with a price and a currency icon. Anything more complex requires TMP.

I like your idea of creating a custom font. That actually seems more fitting for what I’m trying to do anyway, as the picture is “part of the text” rather than a separate entity that needs to share space with text.

I cannot use your approximation because I can’t allow approximation. Everything in my UI and the game itself has the same “faulty neon” theme. I use switching materials via a blend of animation and script to make things flicker on and off. Moreover, everything else strictly adheres to the color palette I cobbled together through an agonizing process of trial and error.

I don’t have the visual-design skill required create a close enough approximation to make the buy buttons look like a natural fit.

For me, getting the materials with the glow shaders to govern the look of my text and create an exact match with the other text in my UI is my only option.

The Shaders and a lot of those properties are specific to SDF related functionality. The properties do not add any overhead or anything so no point removing them.

The mobile distance field shader is very efficient using shader keywords to disable some of the functionality when needed.

So basing a custom shader on the Mobile distance field should be fine and would work.

Modifying SDF shaders is certainly more complicated than normal shaders. Having said that a new set of URP and HDRP shaders with Shader Graph compatibility are coming and those will be easier to modify / tweak. That is for those into shaders.

There is no public repository. Maybe some day.

I will still investigate potential changes to the Mask component for it to be able to do a compound stencil. Not sure yet on feasibility and timeline but I should be able to provide more insight tomorrow.

Thanks for answer but really i’m creating games on mobile. So even float property affects it’s performance when you go for android 5.0. Because of that i use half as much as i can with hlsl written shader. So i have to delete lots of extra things if i want to do it in 3d for low end mobile devices. This is why i criticized. Now i can write lots of shaders but really the only package that restricts me a lot is TMPro. If you can do some kind of override property option or let us in some kind of basic way to program our shader it would be perfect for anyone.

The mobile SDF shader is designed for mobile and OpenGL ES2.0 compatible. It is actually a pretty simple shader that works on the oldest of hardware which at the time was an iPhone 3 when they were first created.

Properties / Uniforms do not add any overhead to a shader in terms of performance. They can have an impact on loading but I doubt it is measurable even on old mobile devices.

The shaders use floats, fixed, half where necessary.

Again, the mobile SDF shader is as efficient as can be and deleting these properties won’t have any impact on performance.

Some of these properties are required for the signed distance field but again these are uniform / constants so no cost there.

1 Like