三国卡牌客户端基础资源仓库
yyl
9 天以前 3978aaadf9466a5910f80679a7930aff6d709283
同步复制资源到OutputPath
3个文件已修改
175 ■■■■■ 已修改文件
Assets/Editor/AssetBundleBrowser/AssetBundleBuildTab.cs 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Tool/ClientPackage.cs 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/YooAsset/YooAssetBuildTool.cs 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/AssetBundleBrowser/AssetBundleBuildTab.cs
@@ -291,8 +291,7 @@
                EditorGUILayout.Space();
                GUILayout.BeginHorizontal();
                var newPath = EditorGUILayout.TextField("Output Path", m_UserData.m_OutputPath);
                if ((newPath != m_UserData.m_OutputPath) &&
                     (newPath != string.Empty))
                if (newPath != m_UserData.m_OutputPath)
                {
                    m_UserData.m_UseDefaultPath = false;
                    m_UserData.m_OutputPath = newPath;
@@ -605,7 +604,7 @@
        private void ExecuteBuildAll()
        {
            // 使用 YooAsset 全量打包所有 Package(含 HybridCLR)
            if (!YooAssetBuildTool.BuildAllPackagesCore(incremental: false))
            if (!YooAssetBuildTool.BuildAllPackagesCore(incremental: false, m_UserData.m_OutputPath))
            {
                Debug.LogError("[AssetBundleBuildTab] YooAsset 全量打包失败!");
                return;
@@ -1011,7 +1010,7 @@
        {
            Debug.LogError("Start to build APK, this may take a while...");
            packageIndex++;
            var outputPath = Application.dataPath.Replace("Assets", m_UserData.m_OutputPath);
            var outputPath = GetResolvedOutputPath();
            ClientPackage.BuildPublishers(ClientPackage.SDK_PLUGIN_PROJECT, outputPath, ApkOutputPath, publishers, packageIndex, false, false);
            Debug.LogError("Finished building APK.");
        }
@@ -1019,7 +1018,7 @@
        private void ExecuteBuildClientPackageDevelopApk()
        {
            packageIndex++;
            var outputPath = Application.dataPath.Replace("Assets", m_UserData.m_OutputPath);
            var outputPath = GetResolvedOutputPath();
            ClientPackage.BuildPublishers(ClientPackage.SDK_PLUGIN_PROJECT, outputPath, ApkOutputPath, publishers, packageIndex, true, false);
        }
@@ -1031,7 +1030,7 @@
                return;
            }
            packageIndex++;
            var assetBundlePath = Application.dataPath.Replace("Assets", m_UserData.m_OutputPath);
            var assetBundlePath = GetResolvedOutputPath();
            ClientPackage.ExportAndroidProject(publishers, packageIndex, false, AndroidExportPath, assetBundlePath, ExportForAppBundle);
        }
@@ -1043,10 +1042,26 @@
                return;
            }
            packageIndex++;
            var assetBundlePath = Application.dataPath.Replace("Assets", m_UserData.m_OutputPath);
            var assetBundlePath = GetResolvedOutputPath();
            ClientPackage.ExportAndroidProject(publishers, packageIndex, true, AndroidExportPath, assetBundlePath, ExportForAppBundle);
        }
        private string GetResolvedOutputPath()
        {
            var projectRoot = Directory.GetParent(Application.dataPath).FullName;
            if (string.IsNullOrWhiteSpace(m_UserData.m_OutputPath))
            {
                return projectRoot;
            }
            if (Path.IsPathRooted(m_UserData.m_OutputPath))
            {
                return Path.GetFullPath(m_UserData.m_OutputPath);
            }
            return Path.GetFullPath(Path.Combine(projectRoot, m_UserData.m_OutputPath));
        }
        private void ExecuteBuildClientPackageStandalone()
        {
            packageIndex++;
Assets/Editor/Tool/ClientPackage.cs
@@ -156,7 +156,7 @@
            for (int i = 0; i < smallPackages.Count; i++)
            {
#if UNITY_ANDROID
                BuildApk(_sdkPath, _output, smallPackages[i], _buildIndex, _development);
                BuildApk(_sdkPath, _output, smallPackages[i], _buildIndex, _development, _assetBundlePath);
#elif UNITY_IOS
                BuildIpa(_sdkPath, smallPackages[i], _buildIndex, _replace);
#endif
@@ -189,7 +189,7 @@
            for (int i = 0; i < halfPackages.Count; i++)
            {
#if UNITY_ANDROID
                BuildApk(_sdkPath, _output, halfPackages[i], _buildIndex, _development);
                BuildApk(_sdkPath, _output, halfPackages[i], _buildIndex, _development, _assetBundlePath);
#elif UNITY_IOS
                BuildIpa(_sdkPath, halfPackages[i], _buildIndex, _replace);
#endif
@@ -208,7 +208,7 @@
            for (int i = 0; i < bigPackages.Count; i++)
            {
#if UNITY_ANDROID
                BuildApk(_sdkPath, _output, bigPackages[i], _buildIndex, _development);
                BuildApk(_sdkPath, _output, bigPackages[i], _buildIndex, _development, _assetBundlePath);
#elif UNITY_IOS
                BuildIpa(_sdkPath, bigPackages[i], _buildIndex, _replace);
#endif
@@ -217,7 +217,7 @@
    }
    public static void BuildApk(string _sdkPath, string _output, string _publisher, int _buildIndex, bool _development)
    public static void BuildApk(string _sdkPath, string _output, string _publisher, int _buildIndex, bool _development, string _streamingAssetsOutputPath = null)
    {
        PreBuild(_publisher, _buildIndex);
        var auditTimeFile = StringUtility.Concat(Application.dataPath, Path.DirectorySeparatorChar.ToString(), "Resources/Config/AuditTime.txt");
@@ -359,6 +359,12 @@
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
        if (_streamingAssetsOutputPath != null && !YooAssetBuildTool.CopyStreamingAssetsToOutputPath(_streamingAssetsOutputPath))
        {
            Debug.LogError("[ClientPackage] 拷贝 StreamingAssets 到资源输出目录失败,中止 APK 构建。TARGET=" + _streamingAssetsOutputPath);
            return;
        }
        // 确保不以 Gradle 工程模式输出(HybridCLR StripAOT 步骤会临时置为 true,若未还原则会输出文件夹而非 APK)
        EditorUserBuildSettings.exportAsGoogleAndroidProject = false;
@@ -440,6 +446,12 @@
        //     Debug.LogWarningFormat("AssetBundle路径为空或不存在: {0},导出工程将不包含游戏资源", _assetBundlePath);
        // }
        if (_assetBundlePath != null && !YooAssetBuildTool.CopyStreamingAssetsToOutputPath(_assetBundlePath))
        {
            Debug.LogError("[ClientPackage] 拷贝 StreamingAssets 到资源输出目录失败,中止 Android 工程导出。TARGET=" + _assetBundlePath);
            return;
        }
        // 关键设置:导出为Gradle工程而非直接打APK
        EditorUserBuildSettings.exportAsGoogleAndroidProject = true;
        EditorUserBuildSettings.androidBuildSystem = AndroidBuildSystem.Gradle;
Assets/Editor/YooAsset/YooAssetBuildTool.cs
@@ -404,7 +404,7 @@
    /// <summary>
    /// 资源打包核心逻辑(不含确认对话框),返回是否全部成功。
    /// </summary>
    public static bool BuildAllPackagesCore(bool incremental)
    public static bool BuildAllPackagesCore(bool incremental, string streamingAssetsOutputPath = null)
    {
        CollectResBeforeUpdate.SyncCollectors();
@@ -467,15 +467,129 @@
            success = CopyStartupConfigsToStreamingAssets();
        }
        if (success && streamingAssetsOutputPath != null)
        {
            success = CopyStreamingAssetsToOutputPath(streamingAssetsOutputPath);
        }
        AssetDatabase.Refresh();
        return success;
    }
    public static bool CopyStreamingAssetsToOutputPath(string outputPath)
    {
        bool sourceStartupConfigsCopied = false;
        try
        {
            sourceStartupConfigsCopied = CopyStartupConfigsToStreamingAssets();
        }
        catch (Exception ex)
        {
            Debug.LogError($"[YooAssetBuildTool] 补齐 StreamingAssets 启动配置异常,将继续拷贝现有 StreamingAssets。error={ex}");
        }
        if (!sourceStartupConfigsCopied)
        {
            Debug.LogWarning("[YooAssetBuildTool] 补齐 StreamingAssets 启动配置失败,将继续拷贝现有 StreamingAssets。");
        }
        string sourceRoot = System.IO.Path.Combine(Application.dataPath, "StreamingAssets");
        string destRoot = ResolveOutputDirectory(outputPath);
        if (!System.IO.Directory.Exists(sourceRoot))
        {
            Debug.LogError($"[YooAssetBuildTool] StreamingAssets 源目录不存在: {sourceRoot}");
            return false;
        }
        string sourceFullPath = NormalizeFullPath(sourceRoot);
        string destFullPath = NormalizeFullPath(destRoot);
        if (string.Equals(sourceFullPath, destFullPath, StringComparison.OrdinalIgnoreCase))
        {
            Debug.LogWarning($"[YooAssetBuildTool] StreamingAssets 输出目录与源目录相同,跳过拷贝: {destFullPath}");
            return true;
        }
        if (destFullPath.StartsWith(sourceFullPath + "/", StringComparison.OrdinalIgnoreCase))
        {
            Debug.LogError($"[YooAssetBuildTool] StreamingAssets 输出目录不能位于源目录内部: {destFullPath}");
            return false;
        }
        System.IO.Directory.CreateDirectory(destFullPath);
        int copiedCount = 0;
        foreach (var sourceFile in System.IO.Directory.GetFiles(sourceFullPath, "*", System.IO.SearchOption.AllDirectories))
        {
            if (string.Equals(System.IO.Path.GetExtension(sourceFile), ".meta", StringComparison.OrdinalIgnoreCase))
            {
                continue;
            }
            string relativePath = sourceFile.Substring(sourceFullPath.Length).TrimStart('\\', '/');
            string destFile = System.IO.Path.Combine(destFullPath, relativePath);
            string destDir = System.IO.Path.GetDirectoryName(destFile);
            if (!System.IO.Directory.Exists(destDir))
            {
                System.IO.Directory.CreateDirectory(destDir);
            }
            System.IO.File.Copy(sourceFile, destFile, true);
            copiedCount++;
        }
        bool configCopied = false;
        try
        {
            configCopied = CopyStartupConfigsToYooDirectory(System.IO.Path.Combine(destFullPath, "yoo"));
        }
        catch (Exception ex)
        {
            Debug.LogError($"[YooAssetBuildTool] 补齐输出目录启动配置异常,不阻塞 StreamingAssets 输出。error={ex}");
        }
        if (!configCopied)
        {
            Debug.LogWarning($"[YooAssetBuildTool] 补齐输出目录启动配置失败,请检查输出目录: {System.IO.Path.Combine(destFullPath, "yoo")}");
        }
        Debug.Log($"[YooAssetBuildTool] 已拷贝 StreamingAssets 到输出目录: {copiedCount} 个文件,from={sourceFullPath}, to={destFullPath}");
        return true;
    }
    private static string ResolveOutputDirectory(string outputPath)
    {
        string projectRoot = System.IO.Directory.GetParent(Application.dataPath).FullName;
        if (string.IsNullOrWhiteSpace(outputPath))
        {
            return projectRoot;
        }
        string normalizedPath = outputPath.Replace('\\', '/');
        if (System.IO.Path.IsPathRooted(normalizedPath))
        {
            return System.IO.Path.GetFullPath(normalizedPath);
        }
        return System.IO.Path.GetFullPath(System.IO.Path.Combine(projectRoot, normalizedPath));
    }
    private static string NormalizeFullPath(string path)
    {
        return System.IO.Path.GetFullPath(path).TrimEnd('\\', '/').Replace('\\', '/');
    }
    public static bool CopyStartupConfigsToStreamingAssets()
    {
        string sourceConfigDir = System.IO.Path.Combine(Application.dataPath, "ResourcesOut", "Config");
        string streamingAssetsDir = System.IO.Path.Combine(Application.dataPath, "StreamingAssets", "yoo");
        string streamingConfigDir = System.IO.Path.Combine(streamingAssetsDir, "config");
        return CopyStartupConfigsToYooDirectory(streamingAssetsDir);
    }
    private static bool CopyStartupConfigsToYooDirectory(string targetYooDir)
    {
        string sourceConfigDir = System.IO.Path.Combine(Application.dataPath, "ResourcesOut", "Config");
        string yooDir = targetYooDir;
        string streamingConfigDir = System.IO.Path.Combine(yooDir, "config");
        if (!System.IO.Directory.Exists(sourceConfigDir))
        {
@@ -483,12 +597,12 @@
            return false;
        }
        System.IO.Directory.CreateDirectory(streamingAssetsDir);
        System.IO.Directory.CreateDirectory(yooDir);
        System.IO.Directory.CreateDirectory(streamingConfigDir);
        bool success = true;
        string initialFunctionSrc = System.IO.Path.Combine(sourceConfigDir, "InitialFunction.txt");
        string initialFunctionDst = System.IO.Path.Combine(streamingAssetsDir, "InitialFunction.txt");
        string initialFunctionDst = System.IO.Path.Combine(yooDir, "InitialFunction.txt");
        if (System.IO.File.Exists(initialFunctionSrc))
        {
            System.IO.File.Copy(initialFunctionSrc, initialFunctionDst, true);
@@ -525,7 +639,7 @@
            Debug.LogWarning($"[YooAssetBuildTool] 未找到 OPConfig 配置: {sourceConfigDir}");
        }
        Debug.Log($"[YooAssetBuildTool] 已拷贝启动配置到 StreamingAssets: InitialFunction={(System.IO.File.Exists(initialFunctionDst) ? "ok" : "missing")}, OPConfig={opConfigCount}, 目录={streamingAssetsDir}");
        Debug.Log($"[YooAssetBuildTool] 已拷贝启动配置到 Yoo 目录: InitialFunction={(System.IO.File.Exists(initialFunctionDst) ? "ok" : "missing")}, OPConfig={opConfigCount}, 目录={yooDir}");
        return success;
    }