179 lines
8.7 KiB
C#
179 lines
8.7 KiB
C#
using System.Text;
|
||
using UnityEditor;
|
||
using UnityEditor.AddressableAssets;
|
||
using UnityEditor.AddressableAssets.Settings;
|
||
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
||
using UnityEngine;
|
||
|
||
/// <summary>
|
||
/// AA 依赖链修复迁移工具(一次性)。
|
||
///
|
||
/// 【背景】Addressables 加载 bundle 时会递归加载其依赖 bundle,而构建报告显示存在
|
||
/// 跨玩法依赖链,导致"未登录就加载鱼包 / 进 A 玩法拉 B 玩法鱼包":
|
||
/// defaultlocalgroup → fish_xjmh → fish_hhwk (启动链:默认音频一碰 D LG 全链拖入)
|
||
/// fish_flzy → fish_hhwk (进 FLZY 房拉 HHWK 鱼包)
|
||
/// gameuires → fish_xjmh (进任何房间拉 XJMH 鱼包)
|
||
///
|
||
/// 【修复内容】(对应 2026-10-08 16:41 构建报告分析出的确切依赖边)
|
||
/// 1. PW_Enemy_4000.prefab(XJMH Boss,误在 D LG)→ Fish_XJMH 组 断 D LG→fish_xjmh
|
||
/// 2. XJMHCreateFish.asset(XJMH 配置,误在 D LG)→ Fish_XJMH 组
|
||
/// 3. 新建 SharedRes 组:Game177_baigujing.png(HHWK 图鉴贴图被 XJMH 小丑扑克引用)、
|
||
/// fish_4003 Variant.png(HHWK 图鉴贴图被 FLZY 闪电引用)→ SharedRes
|
||
/// 断 fish_xjmh→fish_hhwk、fish_flzy→fish_hhwk(两边都只依赖小共享包)
|
||
/// 4. GameMainPanelXJMH 引用的 7 个 XJMH 资源(Boss出场特效/帮助Item/技能sprite)
|
||
/// → GameUIRes 组 断 gameuires→fish_xjmh
|
||
/// (若鱼包资产也引用它们,产生 fish_xjmh→gameuires 边——进房必载面板,无害)
|
||
///
|
||
/// 【使用】Unity 菜单 Tools → AA依赖修复 → 执行修复并重建Addressables,
|
||
/// 完成后用 AABundleMonitor 悬浮窗验证:启动仅 4 个包、进房只加当前玩法鱼包。
|
||
/// </summary>
|
||
public static class AAFixDependencyMigration
|
||
{
|
||
[MenuItem("Tools/AA依赖修复/执行修复并重建Addressables")]
|
||
public static void Run()
|
||
{
|
||
if (!EditorUtility.DisplayDialog("AA依赖修复",
|
||
"将执行以下迁移(断掉跨玩法 bundle 依赖链):\n\n" +
|
||
"1. PW_Enemy_4000 / XJMHCreateFish → Fish_XJMH 组\n" +
|
||
"2. 新建 SharedRes 组,移入 2 张被跨玩法引用的贴图\n" +
|
||
"3. GameMainPanelXJMH 引用的 7 个资源 → GameUIRes 组\n\n" +
|
||
"迁移完成后可选择立即重建 Addressables。\n继续?",
|
||
"执行", "取消"))
|
||
return;
|
||
|
||
var settings = AddressableAssetSettingsDefaultObject.Settings;
|
||
if (settings == null)
|
||
{
|
||
Debug.LogError("[AA依赖修复] 找不到 AddressableAssetSettings");
|
||
return;
|
||
}
|
||
|
||
var log = new StringBuilder();
|
||
|
||
// ---------- ① D LG 里误放的 XJMH 资产 → Fish_XJMH(断 D LG→fish_xjmh 启动链) ----------
|
||
var fishXjmh = settings.FindGroup("Fish_XJMH");
|
||
if (fishXjmh == null) { Debug.LogError("[AA依赖修复] 找不到 Fish_XJMH 组"); return; }
|
||
|
||
MoveWithLabels(settings, fishXjmh,
|
||
"Assets/MyGame/aa/Game/XJMH/Boss/XingJiXunHang/PW_Enemy_4000.prefab",
|
||
new[] { "FishPrefab", "XJMH" }, log);
|
||
MoveWithLabels(settings, fishXjmh,
|
||
"Assets/MyGame/aa/UI/Game/XJMH/XJMHCreateFish.asset",
|
||
new[] { "XJMH" }, log);
|
||
|
||
// ---------- ② 新建 SharedRes 组,移入被跨玩法引用的贴图(断 xjmh/flzy→hhwk) ----------
|
||
var shared = settings.FindGroup("SharedRes");
|
||
if (shared == null)
|
||
{
|
||
shared = CreateGroupLike(settings, "SharedRes", "Fish_XJMH");
|
||
log.AppendLine("[组] 已创建 SharedRes(打包配置复制自 Fish_XJMH)");
|
||
}
|
||
|
||
// 保留原 TuJian/HHWK 标签:HHWK 玩法的图鉴 Sprite 交集加载(TuJian+HHWK)仍能命中,
|
||
// 只是从 SharedRes 包里取;XJMH/FLZY 对它们的引用改为依赖小共享包
|
||
MoveKeepLabels(settings, shared, "Assets/Art/HHWK/res/texture/dynamic/Game177_baigujing.png", log);
|
||
MoveKeepLabels(settings, shared, "Assets/Art/HHWK/TuJianTexture/fish_4003 Variant.png", log);
|
||
|
||
// ---------- ③ GameMainPanelXJMH 引用的资源 → GameUIRes(断 gameuires→fish_xjmh) ----------
|
||
var gameUi = settings.FindGroup("GameUIRes");
|
||
if (gameUi == null) { Debug.LogError("[AA依赖修复] 找不到 GameUIRes 组"); return; }
|
||
|
||
string[] guiTargets =
|
||
{
|
||
"Assets/Art/XJMH/pw/pw_prefab/game/effect/PW_Effect_Boss_Appear.prefab",
|
||
"Assets/Art/XJMH/pw/pw_prefab/item/PW_HelpItem1.prefab",
|
||
"Assets/Art/XJMH/pw/pw_prefab/item/PW_HelpItem2.prefab",
|
||
"Assets/Art/XJMH/pw/pw_prefab/item/PW_SetLockItem.prefab",
|
||
"Assets/Art/XJMH/pw/pw_sprite/common/zd_jn_sd.png",
|
||
"Assets/Art/XJMH/pw/pw_sprite/common/zd_jn_ss.png",
|
||
"Assets/Art/XJMH/pw/pw_sprite/common/zd_jn_zd.png",
|
||
};
|
||
foreach (var t in guiTargets)
|
||
MoveKeepLabels(settings, gameUi, t, log);
|
||
|
||
AssetDatabase.SaveAssets();
|
||
Debug.Log("[AA依赖修复] 迁移完成:\n" + log);
|
||
|
||
// ---------- ④ 重建 ----------
|
||
if (EditorUtility.DisplayDialog("AA依赖修复",
|
||
"迁移完成:\n" + log + "\n现在重建 Addressables?(约几分钟)",
|
||
"立即重建", "稍后手动重建"))
|
||
{
|
||
Debug.Log("[AA依赖修复] 开始重建 Addressables...");
|
||
AddressableAssetSettings.BuildPlayerContent(out var result);
|
||
if (result == null || !string.IsNullOrEmpty(result.Error))
|
||
{
|
||
Debug.LogError("[AA依赖修复] 构建失败: " + (result != null ? result.Error : "无返回结果"));
|
||
EditorUtility.DisplayDialog("AA依赖修复", "构建失败: " + (result != null ? result.Error : "无返回结果"), "确定");
|
||
}
|
||
else
|
||
{
|
||
Debug.Log("[AA依赖修复] 构建完成");
|
||
EditorUtility.DisplayDialog("AA依赖修复",
|
||
"构建完成!\n\n验证步骤:\n" +
|
||
"1. Play 启动到登录页 → 悬浮窗应只有 4 个包(builtinshaders/LoginUIRes/DefaultLocalGroup/Turret)\n" +
|
||
"2. 进任一玩法房间 → 只新增该玩法的鱼包 + gameuires", "确定");
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>移动资产到目标组并覆盖标签</summary>
|
||
private static void MoveWithLabels(AddressableAssetSettings settings, AddressableAssetGroup target,
|
||
string path, string[] labels, StringBuilder log)
|
||
{
|
||
string guid = AssetDatabase.AssetPathToGUID(path);
|
||
if (string.IsNullOrEmpty(guid))
|
||
{
|
||
log.AppendLine("[跳过] 找不到资产: " + path);
|
||
return;
|
||
}
|
||
var entry = settings.CreateOrMoveEntry(guid, target);
|
||
if (entry == null)
|
||
{
|
||
log.AppendLine("[跳过] 移动失败: " + path);
|
||
return;
|
||
}
|
||
entry.labels.Clear();
|
||
foreach (var l in labels)
|
||
entry.labels.Add(l);
|
||
log.AppendLine($"[移动] {path}\n → {target.name}(标签: {string.Join(",", labels)})");
|
||
}
|
||
|
||
/// <summary>移动资产到目标组,保留原有标签</summary>
|
||
private static void MoveKeepLabels(AddressableAssetSettings settings, AddressableAssetGroup target,
|
||
string path, StringBuilder log)
|
||
{
|
||
string guid = AssetDatabase.AssetPathToGUID(path);
|
||
if (string.IsNullOrEmpty(guid))
|
||
{
|
||
log.AppendLine("[跳过] 找不到资产: " + path);
|
||
return;
|
||
}
|
||
var entry = settings.CreateOrMoveEntry(guid, target);
|
||
if (entry == null)
|
||
{
|
||
log.AppendLine("[跳过] 移动失败: " + path);
|
||
return;
|
||
}
|
||
log.AppendLine($"[移动] {path}\n → {target.name}(保留标签: {string.Join(",", entry.labels)})");
|
||
}
|
||
|
||
/// <summary>按源组的打包配置(BundledAssetGroupSchema/ContentUpdateGroupSchema)创建新组。
|
||
/// AddSchema(schema) 内部会复制 schema 并正确挂到新组上,无需手动 CopySerialized。</summary>
|
||
private static AddressableAssetGroup CreateGroupLike(AddressableAssetSettings settings,
|
||
string newName, string srcGroupName)
|
||
{
|
||
var src = settings.FindGroup(srcGroupName);
|
||
var group = settings.CreateGroup(newName, false, false, false, null);
|
||
|
||
var srcBundled = src.GetSchema<BundledAssetGroupSchema>();
|
||
if (srcBundled != null)
|
||
group.AddSchema(srcBundled, false);
|
||
|
||
var srcContent = src.GetSchema<ContentUpdateGroupSchema>();
|
||
if (srcContent != null)
|
||
group.AddSchema(srcContent, false);
|
||
|
||
return group;
|
||
}
|
||
} |