[Unity editor extension practice] After upgrading the Unity2021 version, adding new pictures to the atlas is abnormal

Problem: After Unity2018 is upgraded to Unity2021, the internalID of the newly added picture is 0 when opening the atlas (Figure 1), and the left side is the meta file information before modification. As a result, after the image is pushed to the prefab, the prefab does not save the image information correctly (Figure 2), and the loaded prefab image is empty after the game is running.

Version: Unity 2018.4.36f1 upgrade to Unity 2021.3.19f1

Atlas tool: TexturePacker

Figure 1. Comparison of pictures before and after meta modification
Figure 2. Comparison of prefabrication before and after modification

 Modification idea: Since no specific reason for the InternalID being 0 was found, the internalID is being modified. After the atlas data is generated, traverse the Sprite, if m_SpriteID is 00000000000000000800000000000000, use GUID.Generate() to generate a m_SpriteID. If m_InternalID is 0, use m_SpriteID.GetHashCode() to generate an m_InternalID. Loop through the modified SerializedProperty, modify m_InternalIDToNameTable and nameFileIdTable, and save the meta file.

Specific code:

private static void DoApply()
    {
        string path = AssetDatabase.GetAssetPath(rgbImage);
        TextureImporter textureImporter = AssetImporter.GetAtPath(path) as TextureImporter;
        var m_CachedSerializedObject = new SerializedObject(textureImporter);
        m_CachedSerializedObject?.Update();
        var _nameTable = m_CachedSerializedObject.FindProperty("m_InternalIDToNameTable");
        if (_nameTable.arraySize > 0)//旧图集
        {
            var spriteSheetSo = m_CachedSerializedObject.FindProperty("m_SpriteSheet.m_Sprites");
            if (spriteSheetSo.arraySize > 0)
            {
                List<SerializedProperty> _changeSPList = new List<SerializedProperty>();
                SerializedProperty sp = null;
                for (int i = 0; i < spriteSheetSo.arraySize; ++i)
                {
                    sp = spriteSheetSo.GetArrayElementAtIndex(i);
                    if ("00000000000000000800000000000000" == sp.FindPropertyRelative("m_SpriteID").stringValue)
                    {
                        _changeSPList.Add(sp);
                        string _guid = GUID.Generate().ToString();
                        sp.FindPropertyRelative("m_SpriteID").stringValue = _guid;
                        if (sp.FindPropertyRelative("m_InternalID").longValue == 0)
                        {
                            sp.FindPropertyRelative("m_InternalID").longValue = _guid.GetHashCode();
                        }
                    }
                }
                if (_changeSPList.Count > 0)
                {
                    Dictionary<string, long> _tempNameFileIdTableDic = new Dictionary<string, long>();
                    int _index = _nameTable.arraySize;
                    for (int i = 0; i < _changeSPList.Count; i++)//修改m_InternalIDToNameTable
                    {
                        _nameTable.InsertArrayElementAtIndex(_index + i);
                        string _spriteName = _changeSPList[i].FindPropertyRelative("m_Name").stringValue;
                        long _internalID = _changeSPList[i].FindPropertyRelative("m_InternalID").longValue;
                        var _nameTableTemp = _nameTable.GetArrayElementAtIndex(_index + i);
                        _nameTableTemp.FindPropertyRelative("first.second").longValue = _internalID;
                        _nameTableTemp.FindPropertyRelative("second").stringValue = _spriteName;
                        _tempNameFileIdTableDic[_spriteName] = _internalID;
                    }
                    var nameTableSp = m_CachedSerializedObject.FindProperty("m_SpriteSheet.m_NameFileIdTable");
                    if (nameTableSp.arraySize > 0)//修改nameFileIdTable
                    {
                        SerializedProperty nameSp = nameTableSp.GetArrayElementAtIndex(0);
                        for (int i = 0; i < nameTableSp.arraySize; i++)
                        {
                            if (nameSp.FindPropertyRelative("second").longValue == 0)
                            {
                                string _name = nameSp.FindPropertyRelative("first").stringValue;
                                nameSp.FindPropertyRelative("second").longValue = _tempNameFileIdTableDic[_name];
                            }
                            nameSp.Next(false);
                        }
                    }
                    m_CachedSerializedObject.ApplyModifiedProperties();
                    AssetDatabase.ForceReserializeAssets(new[] { path }, ForceReserializeAssetsOptions.ReserializeMetadata);

                }
            }
        }
    }

Then separate the atlas again to modify the value of InternalID to 0.

Note: The SpriteID generation rules are inconsistent with the Unity generation rules, and no rules for Unity to generate SpriteIDs were found.

Guess you like

Origin blog.csdn.net/qq_33461689/article/details/130055172