【Unityエディタ拡張実践】Unity2021バージョンアップ後、アトラスへの新規画像の追加が異常になる

問題: Unity2018 から Unity2021 にアップグレードした後、アトラスを開くと、新しく追加された画像の InternalID が 0 (図 1) になり、左側が変更前のメタ ファイル情報になります。その結果、画像がプレハブにプッシュされた後、プレハブは画像情報を正しく保存せず (図 2)、ゲームの実行後、ロードされたプレハブ イメージは空になります。

バージョン: Unity 2018.4.36f1 から Unity 2021.3.19f1 へのアップグレード

アトラスツール: TexturePacker

図 1. メタ修正前後の画像の比較
図 2. 改造前と改造後のプレハブの比較

 修正案: InternalID が 0 になる具体的な理由が見つからないため、internalID を修正します。アトラス データが生成された後、スプライトをトラバースします。m_SpriteID が 000000000000000000000000000000000 の場合は、GUID.Generate() を使用して m_SpriteID を生成します。m_InternalID が 0 の場合、m_SpriteID.GetHashCode() を使用して m_InternalID を生成します。変更された SerializedProperty をループし、m_InternalIDToNameTable と nameFileIdTable を変更して、メタ ファイルを保存します。

具体的なコード:

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);

                }
            }
        }
    }

次に、アトラスを再度分割して、InternalID の値を 0 に変更します。

注: SpriteID の生成ルールは Unity の生成ルールと矛盾しており、Unity が SpriteID を生成するルールが見つかりませんでした。

おすすめ

転載: blog.csdn.net/qq_33461689/article/details/130055172