ZoeAppClass/Assets/Scripts/Editor/AddressableGamesMigration.cs

133 lines
5.3 KiB
C#

#if UNITY_EDITOR
using System;
using System.IO;
using UnityEditor;
using UnityEditor.AddressableAssets;
using UnityEditor.AddressableAssets.Settings;
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
using UnityEngine;
/// <summary>
/// Move somente Assets/Resources/Games para fora de Resources e cria um grupo remoto por jogo.
/// As referências .meta são preservadas pelo AssetDatabase.MoveAsset.
/// </summary>
public static class AddressableGamesMigration
{
private const string SourceRoot = "Assets/Resources/Games";
private const string TargetRoot = "Assets/RemoteResources/Games";
private const string GroupPrefix = "RemoteGame_";
[MenuItem("Tools/Addressables/Migrar Games para download sob demanda")]
public static void Migrate()
{
if (EditorApplication.isPlayingOrWillChangePlaymode)
{
Debug.LogError("Saia do Play Mode antes da migração.");
return;
}
if (AssetDatabase.IsValidFolder(SourceRoot))
{
EnsureFolder("Assets", "RemoteResources");
if (AssetDatabase.IsValidFolder(TargetRoot))
{
Debug.LogError("A pasta de destino já existe: " + TargetRoot);
return;
}
string moveError = AssetDatabase.MoveAsset(SourceRoot, TargetRoot);
if (!string.IsNullOrEmpty(moveError))
{
Debug.LogError("Não foi possível mover Games: " + moveError);
return;
}
}
if (!AssetDatabase.IsValidFolder(TargetRoot))
{
Debug.LogError("Pasta não encontrada: " + TargetRoot);
return;
}
AddressableAssetSettings settings = AddressableAssetSettingsDefaultObject.GetSettings(true);
settings.BuildRemoteCatalog = true;
settings.RemoteCatalogBuildPath.SetVariableByName(settings, AddressableAssetSettings.kRemoteBuildPath);
settings.RemoteCatalogLoadPath.SetVariableByName(settings, AddressableAssetSettings.kRemoteLoadPath);
string[] infoGuids = AssetDatabase.FindAssets("Info t:GameObject", new[] { TargetRoot });
int games = 0;
int entries = 0;
foreach (string infoGuid in infoGuids)
{
string infoPath = AssetDatabase.GUIDToAssetPath(infoGuid).Replace('\\', '/');
if (!infoPath.EndsWith("/Info.prefab", StringComparison.OrdinalIgnoreCase)) continue;
string gameFolder = Path.GetDirectoryName(infoPath).Replace('\\', '/');
string relativeFolder = gameFolder.Substring(TargetRoot.Length).TrimStart('/');
string groupName = GroupPrefix + Sanitize(relativeFolder);
AddressableAssetGroup group = settings.FindGroup(groupName);
if (group == null)
{
group = settings.CreateGroup(groupName, false, false, false, null,
typeof(BundledAssetGroupSchema), typeof(ContentUpdateGroupSchema));
}
BundledAssetGroupSchema schema = group.GetSchema<BundledAssetGroupSchema>();
if (schema == null) schema = group.AddSchema<BundledAssetGroupSchema>();
schema.BuildPath.SetVariableByName(settings, AddressableAssetSettings.kRemoteBuildPath);
schema.LoadPath.SetVariableByName(settings, AddressableAssetSettings.kRemoteLoadPath);
schema.BundleMode = BundledAssetGroupSchema.BundlePackingMode.PackTogether;
entries += AddEntry(settings, group, infoPath, "Games/" + relativeFolder + "/Info");
string gamePath = gameFolder + "/Game.prefab";
if (File.Exists(gamePath))
entries += AddEntry(settings, group, gamePath, "Games/" + relativeFolder + "/Game");
else
Debug.LogWarning("Game.prefab não encontrado em: " + gameFolder);
EditorUtility.SetDirty(schema);
EditorUtility.SetDirty(group);
games++;
}
EditorUtility.SetDirty(settings);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
Debug.Log("Migração concluída. Jogos: " + games + " | Entradas: " + entries);
EditorUtility.DisplayDialog("Addressables",
"Migração concluída.\n\nJogos: " + games + "\nEntradas: " + entries +
"\n\nAgora faça Build > Clean Build > All e depois Default Build Script.", "OK");
}
private static int AddEntry(AddressableAssetSettings settings, AddressableAssetGroup group, string path, string address)
{
string guid = AssetDatabase.AssetPathToGUID(path);
if (string.IsNullOrEmpty(guid))
{
Debug.LogError("GUID não encontrado: " + path);
return 0;
}
AddressableAssetEntry entry = settings.CreateOrMoveEntry(guid, group, false, false);
entry.address = address.Replace('\\', '/');
return 1;
}
private static void EnsureFolder(string parent, string child)
{
string path = parent + "/" + child;
if (!AssetDatabase.IsValidFolder(path)) AssetDatabase.CreateFolder(parent, child);
}
private static string Sanitize(string value)
{
if (string.IsNullOrEmpty(value)) return "Root";
foreach (char c in Path.GetInvalidFileNameChars()) value = value.Replace(c, '_');
return value.Replace('/', '_').Replace('\\', '_').Replace(' ', '_');
}
}
#endif