Update Sprite Assets button not saving changes

Hi,

I encountered a minor bug with TMP 2.1.4. If you change a Sprite Asset by clicking the ‘Update Sprite Asset’ button, the Sprite Asset will correctly update, however the editor doesn’t recognize it as dirty and therefore does not save the changes once you close the project. The only way I could get it to recognize that the Sprite Asset was updated and for it to save was by manually changing a value on the Sprite Asset.

Again, not the biggest thing since changing a value and changing it back isn’t hard. Also, not sure if this matters but I had updated from 2.1.1 to 2.1.4 (I skipped the other two versions because I was having problems with them). Also, I’m using Unity 2019.4.17.

Thanks,

Kenny

1 Like

Yeah this is still an issue as of 3.0.6 TMP with Unity 2020.3.3f1
What I have been doing is renaming the asset, generating a new one, then replacing the old one with the new one outside of Unity to maintain the connection.
Your method is way better and a lot safer and glad I found it. Still, it would be nice to see this fixed.

Same issue here, perhaps they didn’t set the asset dirty, thus not saving changes on editor exit. I’ve done that before with my own custom asset types

2021.3.9f1 with 3.0.6 TMP still not working. Doesn’t seem like there’s any interest to fix it so I looked into doing it myself via code

Tried setting the asset dirty and it wasn’t enough, I got it working though by doing essentially what the [Update Sprite Asset] button does, you can see here for an idea.

Just add it here
[SerializeField] private TMPro.TMP_SpriteAsset _mySpriteAsset;
then pass it to this method

internal static void UpdateSpriteAsset(TMP_SpriteAsset spriteAsset)
    {
        // Get a list of all the sprites contained in the texture referenced by the sprite asset.
        // This only works if the texture is set to sprite mode.
        string filePath = AssetDatabase.GetAssetPath(spriteAsset.spriteSheet);
        if (string.IsNullOrEmpty(filePath))
            return;
        // Get all the sprites defined in the sprite sheet texture referenced by this sprite asset.
        Sprite[] sprites = AssetDatabase.LoadAllAssetsAtPath(filePath).Select(x => x as Sprite).Where(x => x != null).ToArray();
        // Return if sprite sheet texture does not have any sprites defined in it.
        if (sprites.Length == 0)
        {
            Debug.Log("Sprite Asset <color=#FFFF80>[" + spriteAsset.name + "]</color>'s atlas texture does not appear to have any sprites defined in it. Use the Unity Sprite Editor to define sprites for this texture.", spriteAsset.spriteSheet);
            return;
        }
        List<TMP_SpriteGlyph> spriteGlyphTable = spriteAsset.spriteGlyphTable;
        // Find available glpyh indexes
        uint[] existingGlyphIndexes = spriteGlyphTable.Select(x => x.index).ToArray();
        List<uint> availableGlyphIndexes = new List<uint>();
        uint lastGlyphIndex = existingGlyphIndexes.Length > 0 ? existingGlyphIndexes.Last() : 0;
        int elementIndex = 0;
        for (uint i = 0; i < lastGlyphIndex; i++)
        {
            uint existingGlyphIndex = existingGlyphIndexes[elementIndex];
            if (i == existingGlyphIndex)
                elementIndex += 1;
            else
                availableGlyphIndexes.Add(i);
        }
        // Iterate over sprites contained in the updated sprite sheet to identify new and / or modified sprites.
        for (int i = 0; i < sprites.Length; i++)
        {
            Sprite sprite = sprites[i];
            // Check if current sprites is already contained in the sprite glyph table of the sprite asset.
            TMP_SpriteGlyph spriteGlyph = spriteGlyphTable.FirstOrDefault(x => x.sprite == sprite);
            if (spriteGlyph != null)
            {
                // update existing sprite glyph
                if (spriteGlyph.glyphRect.x != sprite.rect.x || spriteGlyph.glyphRect.y != sprite.rect.y || spriteGlyph.glyphRect.width != sprite.rect.width || spriteGlyph.glyphRect.height != sprite.rect.height)
                    spriteGlyph.glyphRect = new GlyphRect(sprite.rect);
            }
            else
            {
                TMP_SpriteCharacter spriteCharacter;
                // Check if this sprite potentially exists under the same name in the sprite character table.
                if (spriteAsset.spriteCharacterTable != null && spriteAsset.spriteCharacterTable.Count > 0)
                {
                    spriteCharacter = spriteAsset.spriteCharacterTable.FirstOrDefault(x => x.name == sprite.name);
                    spriteGlyph = spriteCharacter != null ? spriteGlyphTable[(int)spriteCharacter.glyphIndex] : null;
                    if (spriteGlyph != null)
                    {
                        // Update sprite reference and data
                        spriteGlyph.sprite = sprite;
                        if (spriteGlyph.glyphRect.x != sprite.rect.x || spriteGlyph.glyphRect.y != sprite.rect.y || spriteGlyph.glyphRect.width != sprite.rect.width || spriteGlyph.glyphRect.height != sprite.rect.height)
                            spriteGlyph.glyphRect = new GlyphRect(sprite.rect);
                    }
                }
                // Add new Sprite Glyph to the table
                spriteGlyph = new TMP_SpriteGlyph();
                // Get available glyph index
                if (availableGlyphIndexes.Count > 0)
                {
                    spriteGlyph.index = availableGlyphIndexes[0];
                    availableGlyphIndexes.RemoveAt(0);
                }
                else
                    spriteGlyph.index = (uint)spriteGlyphTable.Count;
                spriteGlyph.metrics = new GlyphMetrics(sprite.rect.width, sprite.rect.height, -sprite.pivot.x, sprite.rect.height - sprite.pivot.y, sprite.rect.width);
                spriteGlyph.glyphRect = new GlyphRect(sprite.rect);
                spriteGlyph.scale = 1.0f;
                spriteGlyph.sprite = sprite;
                spriteGlyphTable.Add(spriteGlyph);
                spriteCharacter = new TMP_SpriteCharacter(0xFFFE, spriteGlyph);
                spriteCharacter.name = sprite.name;
                spriteCharacter.scale = 1.0f;
                spriteAsset.spriteCharacterTable.Add(spriteCharacter);
            }
        }
        // Update Sprite Character Table to replace unicode 0x0 by 0xFFFE
        for (int i = 0; i < spriteAsset.spriteCharacterTable.Count; i++)
        {
            TMP_SpriteCharacter spriteCharacter = spriteAsset.spriteCharacterTable[i];
            if (spriteCharacter.unicode == 0)
                spriteCharacter.unicode = 0xFFFE;
        }
        // Sort glyph table by glyph index
        spriteAsset.SortGlyphTable();
        spriteAsset.UpdateLookupTables();
        TMPro_EventManager.ON_SPRITE_ASSET_PROPERTY_CHANGED(true, spriteAsset);
    }
1 Like

I reported this bug to Unity, it is being addressed, will report back when I hear more.

2 Likes

FYI, this seems to have been fixed in 2022.3.xxx (at least it works for me :slight_smile: though the issue has not been updated in the Unity bug report console.