三国卡牌客户端基础资源仓库
yyl
10 天以前 0a2ecc5de6394cd538b9e4fc9901a52fd2b2aa8d
漏提交内容
6个文件已添加
397 ■■■■■ 已修改文件
Assets/Editor/AssetBundleBrowser/FixGhostAsset.cs 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/AssetBundleBrowser/FixGhostAsset.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/YooAsset/CollectBuiltinAfterUpdate.cs 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/YooAsset/CollectBuiltinAfterUpdate.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/YooAsset/CollectResBeforeUpdate.cs 302 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/YooAsset/CollectResBeforeUpdate.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/AssetBundleBrowser/FixGhostAsset.cs
New file
@@ -0,0 +1,52 @@
using System.IO;
using UnityEditor;
using UnityEngine;
public static class FixGhostAsset
{
    [MenuItem("Tools/Fix Ghost Asset")]
    public static void Fix()
    {
        const string ghost = "Assets/ResourcesOut/Sprite/HeroDebutHero_510016/HeroDebutSkinTabInfo_5100161.png";
        var guid = AssetDatabase.AssetPathToGUID(ghost);
        var type = AssetDatabase.GetMainAssetTypeAtPath(ghost);
        Debug.Log($"[Ghost] path={ghost}\n  GUID={guid}\n  Type={type}");
        // 直接让 Unity 从索引里删掉
        var ok = AssetDatabase.DeleteAsset(ghost);
        Debug.Log($"[Ghost] DeleteAsset -> {ok}");
        AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
    }
    /// <summary>
    /// 删除 YooAsset 的 AssetDependencyDB 依赖缓存。
    /// 当出现 "Found invalid asset : ..." 这类指向已删除资源的报错时调用。
    /// 该 DB 缓存了旧的 GUID→AssetPath 映射,磁盘文件删除后它不会自动失效,
    /// 删除文件后 YooAsset 会在下次打包时自动重建。
    /// </summary>
    [MenuItem("Tools/Clear YooAsset DependencyDB")]
    public static void ClearYooAssetDependencyDB()
    {
        string projectRoot = Path.GetFullPath(Path.Combine(Application.dataPath, ".."));
        string dbPath = Path.Combine(projectRoot, "Library", "AssetDependencyDB");
        if (File.Exists(dbPath))
        {
            try
            {
                File.Delete(dbPath);
                Debug.Log($"[FixGhostAsset] 已删除 YooAsset 依赖缓存: {dbPath}\n下次打包将自动重建。");
            }
            catch (System.Exception ex)
            {
                Debug.LogError($"[FixGhostAsset] 删除 AssetDependencyDB 失败: {ex.Message}");
            }
        }
        else
        {
            Debug.Log($"[FixGhostAsset] AssetDependencyDB 不存在(可能已删除或尚未生成): {dbPath}");
        }
    }
}
Assets/Editor/AssetBundleBrowser/FixGhostAsset.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dc14395ba27efe14d91a69e4983c8a6c
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Assets/Editor/YooAsset/CollectBuiltinAfterUpdate.cs
New file
@@ -0,0 +1,10 @@
using YooAsset.Editor;
[DisplayName("收集BuiltIn(排除热更前资源)")]
public class CollectBuiltinAfterUpdate : IFilterRule
{
    public bool IsCollectAsset(FilterRuleData data)
    {
        return !CollectResBeforeUpdate.IsBeforeUpdateBuiltinAsset(data.AssetPath);
    }
}
Assets/Editor/YooAsset/CollectBuiltinAfterUpdate.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: da4dc54ec24d90b488d2747e4a4b34c5
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Assets/Editor/YooAsset/CollectResBeforeUpdate.cs
New file
@@ -0,0 +1,302 @@
using System;
using System.IO;
using UnityEditor;
using UnityEngine;
using YooAsset.Editor;
public static class CollectResBeforeUpdate
{
    private const string BuiltinPackageName = "Builtin";
    private const string PrefabPackageName = "Prefab";
    private const string GroupName = "ResBeforeUpdate";
    private const string AfterUpdateGroupName = "BuiltinAfterUpdate";
    private const string CollectBuiltinAfterUpdateRuleName = "CollectBuiltinAfterUpdate";
    private const string BuiltInRoot = "Assets/ResourcesOut/BuiltIn";
    private const string ConfigRoot = "Assets/ResourcesOut/Config";
    private const string InitialFunctionPath = ConfigRoot + "/InitialFunction.txt";
    private const string ResourcesInitialFunctionPath = "Assets/Resources/Config/InitialFunction.txt";
    private static readonly string[] BeforeUpdateBuiltinAssetPaths =
    {
        BuiltInRoot + "/Prefabs/LaunchExWin.prefab",
        BuiltInRoot + "/Sprites/TY_TB_JH1.png",
        BuiltInRoot + "/Sprites/TY_TB_JH2.png",
        BuiltInRoot + "/Sprites/LoadingBottom.png",
        BuiltInRoot + "/Sprites/LoadingSlider.png",
    };
    private static readonly string[] BuiltinConfigPaths =
    {
        ConfigRoot + "/Contact.txt",
        ConfigRoot + "/HelpInfo.txt",
        ConfigRoot + "/PriorBundle.txt",
        ConfigRoot + "/PriorLanguage.txt",
        ConfigRoot + "/ApkUpdateUrl.txt",
        InitialFunctionPath,
    };
    [MenuItem("YooAsset工具/收集热更前资源到Builtin", false, 202)]
    public static void Execute()
    {
        var changed = SyncCollectors();
        EditorUtility.DisplayDialog(
            "CollectResBeforeUpdate",
            changed ? "热更前资源已同步到 Builtin Package。" : "热更前资源收集配置已经是最新。",
            "确定");
    }
    public static bool SyncCollectors()
    {
        var setting = AssetBundleCollectorSettingData.Setting;
        var changed = false;
        var builtinPackage = setting.Packages.Find(package => package.PackageName == BuiltinPackageName);
        if (builtinPackage == null)
        {
            builtinPackage = AssetBundleCollectorSettingData.CreatePackage(BuiltinPackageName);
            changed = true;
            Debug.Log($"[CollectResBeforeUpdate] 创建 Package: {BuiltinPackageName}");
        }
        var group = builtinPackage.Groups.Find(item => item.GroupName == GroupName);
        if (group == null)
        {
            group = AssetBundleCollectorSettingData.CreateGroup(builtinPackage, GroupName);
            changed = true;
            Debug.Log($"[CollectResBeforeUpdate] 创建 Group: {GroupName}");
        }
        changed |= RemoveObsoleteBuiltinRootCollectors(builtinPackage);
        changed |= RemoveDuplicateBeforeUpdateCollectors(setting, builtinPackage, group);
        foreach (var assetPath in BeforeUpdateBuiltinAssetPaths)
        {
            changed |= EnsureCollector(group, assetPath, nameof(PackSeparately), nameof(CollectAll));
        }
        foreach (var configPath in BuiltinConfigPaths)
        {
            changed |= EnsureCollector(group, configPath, nameof(PackSeparately), nameof(CollectAll));
        }
        changed |= EnsureAfterUpdateBuiltinCollector(setting);
        changed |= SyncResourcesInitialFunction();
        if (changed)
        {
            AssetBundleCollectorSettingData.SaveFile();
            AssetDatabase.Refresh();
            Debug.Log("[CollectResBeforeUpdate] 热更前资源收集配置已同步。Builtin 只保留 Launch 白名单,其余 BuiltIn 资源由 Prefab 包收集。");
        }
        else
        {
            Debug.Log("[CollectResBeforeUpdate] 热更前资源收集配置无需更新。");
        }
        return changed;
    }
    public static bool IsBeforeUpdateBuiltinAsset(string assetPath)
    {
        foreach (var beforeUpdatePath in BeforeUpdateBuiltinAssetPaths)
        {
            if (IsSameAssetPath(assetPath, beforeUpdatePath))
                return true;
        }
        return false;
    }
    private static bool EnsureAfterUpdateBuiltinCollector(AssetBundleCollectorSetting setting)
    {
        var prefabPackage = setting.Packages.Find(package => package.PackageName == PrefabPackageName);
        if (prefabPackage == null)
        {
            prefabPackage = AssetBundleCollectorSettingData.CreatePackage(PrefabPackageName);
            Debug.Log($"[CollectResBeforeUpdate] 创建 Package: {PrefabPackageName}");
        }
        var group = prefabPackage.Groups.Find(item => item.GroupName == AfterUpdateGroupName);
        if (group == null)
        {
            group = AssetBundleCollectorSettingData.CreateGroup(prefabPackage, AfterUpdateGroupName);
            Debug.Log($"[CollectResBeforeUpdate] 创建 Group: {AfterUpdateGroupName}");
        }
        return EnsureCollector(group, BuiltInRoot, nameof(PackDirectory), CollectBuiltinAfterUpdateRuleName);
    }
    private static bool RemoveObsoleteBuiltinRootCollectors(AssetBundleCollectorPackage builtinPackage)
    {
        var changed = false;
        foreach (var group in builtinPackage.Groups)
        {
            for (var index = group.Collectors.Count - 1; index >= 0; index--)
            {
                var collector = group.Collectors[index];
                if (!IsSameAssetPath(collector.CollectPath, BuiltInRoot))
                    continue;
                AssetBundleCollectorSettingData.RemoveCollector(group, collector);
                changed = true;
                Debug.Log($"[CollectResBeforeUpdate] 从 Builtin Package 移除整目录 Collector: {collector.CollectPath}");
            }
        }
        return changed;
    }
    private static bool RemoveDuplicateBeforeUpdateCollectors(
        AssetBundleCollectorSetting setting,
        AssetBundleCollectorPackage builtinPackage,
        AssetBundleCollectorGroup targetGroup)
    {
        var changed = false;
        foreach (var package in setting.Packages)
        {
            foreach (var group in package.Groups)
            {
                for (var index = group.Collectors.Count - 1; index >= 0; index--)
                {
                    var collector = group.Collectors[index];
                    if (!IsExactBeforeUpdateCollectPath(collector.CollectPath))
                        continue;
                    if (package == builtinPackage && group == targetGroup)
                        continue;
                    AssetBundleCollectorSettingData.RemoveCollector(group, collector);
                    changed = true;
                    Debug.Log($"[CollectResBeforeUpdate] 从 Package '{package.PackageName}' 移除重复 Collector: {collector.CollectPath}");
                }
            }
        }
        return changed;
    }
    private static bool EnsureCollector(AssetBundleCollectorGroup group, string collectPath, string packRuleName, string filterRuleName)
    {
        var collectorGuid = AssetDatabase.AssetPathToGUID(collectPath);
        if (string.IsNullOrEmpty(collectorGuid))
        {
            Debug.LogWarning($"[CollectResBeforeUpdate] 跳过不存在的资源: {collectPath}");
            return false;
        }
        var changed = false;
        AssetBundleCollector target = null;
        for (var index = group.Collectors.Count - 1; index >= 0; index--)
        {
            var collector = group.Collectors[index];
            if (!IsSameAssetPath(collector.CollectPath, collectPath))
                continue;
            if (target == null)
            {
                target = collector;
            }
            else
            {
                AssetBundleCollectorSettingData.RemoveCollector(group, collector);
                changed = true;
                Debug.Log($"[CollectResBeforeUpdate] 移除重复 Collector: {collector.CollectPath}");
            }
        }
        if (target == null)
        {
            target = new AssetBundleCollector { CollectPath = collectPath };
            AssetBundleCollectorSettingData.CreateCollector(group, target);
            changed = true;
            Debug.Log($"[CollectResBeforeUpdate] 创建 Collector: {collectPath}");
        }
        changed |= SetString(ref target.CollectPath, collectPath);
        changed |= SetString(ref target.CollectorGUID, collectorGuid);
        if (target.CollectorType != ECollectorType.MainAssetCollector)
        {
            target.CollectorType = ECollectorType.MainAssetCollector;
            changed = true;
        }
        changed |= SetString(ref target.AddressRuleName, nameof(AddressByRelativePath));
        changed |= SetString(ref target.PackRuleName, packRuleName);
        changed |= SetString(ref target.FilterRuleName, filterRuleName);
        changed |= SetString(ref target.AssetTags, string.Empty);
        changed |= SetString(ref target.UserData, string.Empty);
        if (changed)
            AssetBundleCollectorSettingData.ModifyCollector(group, target);
        return changed;
    }
    private static bool SyncResourcesInitialFunction()
    {
        var sourceFullPath = ToProjectFullPath(InitialFunctionPath);
        if (!File.Exists(sourceFullPath))
        {
            Debug.LogError($"[CollectResBeforeUpdate] 找不到 ResourcesOut InitialFunction: {InitialFunctionPath}");
            return false;
        }
        var targetFullPath = ToProjectFullPath(ResourcesInitialFunctionPath);
        var targetDirectory = Path.GetDirectoryName(targetFullPath);
        if (!Directory.Exists(targetDirectory))
            Directory.CreateDirectory(targetDirectory);
        var sourceText = File.ReadAllText(sourceFullPath);
        if (File.Exists(targetFullPath) && File.ReadAllText(targetFullPath) == sourceText)
            return false;
        File.WriteAllText(targetFullPath, sourceText);
        AssetDatabase.ImportAsset(ResourcesInitialFunctionPath);
        Debug.Log($"[CollectResBeforeUpdate] 已同步 Resources InitialFunction: {ResourcesInitialFunctionPath}");
        return true;
    }
    private static bool IsExactBeforeUpdateCollectPath(string collectPath)
    {
        if (IsSameAssetPath(collectPath, BuiltInRoot))
            return false;
        foreach (var beforeUpdatePath in BeforeUpdateBuiltinAssetPaths)
        {
            if (IsSameAssetPath(collectPath, beforeUpdatePath))
                return true;
        }
        foreach (var configPath in BuiltinConfigPaths)
        {
            if (IsSameAssetPath(collectPath, configPath))
                return true;
        }
        return false;
    }
    private static bool IsSameAssetPath(string lhs, string rhs)
    {
        return NormalizeAssetPath(lhs).Equals(NormalizeAssetPath(rhs), StringComparison.OrdinalIgnoreCase);
    }
    private static string ToProjectFullPath(string assetPath)
    {
        var projectRoot = Directory.GetParent(Application.dataPath).FullName;
        return Path.Combine(projectRoot, NormalizeAssetPath(assetPath));
    }
    private static string NormalizeAssetPath(string assetPath)
    {
        return string.IsNullOrEmpty(assetPath) ? string.Empty : assetPath.Replace('\\', '/').TrimEnd('/');
    }
    private static bool SetString(ref string target, string value)
    {
        if (target == value)
            return false;
        target = value;
        return true;
    }
}
Assets/Editor/YooAsset/CollectResBeforeUpdate.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7c219d6f90e14464290e8f4b420d26a1
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant: