問題: Unity2018 から Unity2021 にアップグレードした後、アトラスを開くと、新しく追加された画像の InternalID が 0 (図 1) になり、左側が変更前のメタ ファイル情報になります。その結果、画像がプレハブにプッシュされた後、プレハブは画像情報を正しく保存せず (図 2)、ゲームの実行後、ロードされたプレハブ イメージは空になります。
バージョン: Unity 2018.4.36f1 から Unity 2021.3.19f1 へのアップグレード
アトラスツール: TexturePacker
修正案: 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 を生成するルールが見つかりませんでした。