diff --git a/Assets/Editor/PackageExporter.cs b/Assets/Editor/PackageExporter.cs
new file mode 100644
index 0000000..a7830c5
--- /dev/null
+++ b/Assets/Editor/PackageExporter.cs
@@ -0,0 +1,273 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using UnityEditor;
+using UnityEngine;
+
+public class PackageExporter
+ {
+ ///
+ /// 导出 UnityPackage(支持忽略特定文件)
+ ///
+ /// 需要导出的资源路径数组(文件夹或文件)
+ /// 导出文件路径(含.unitypackage扩展名)
+ /// 需要忽略的文件/文件夹模式数组
+ /// 是否包含依赖资源
+ /// 是否递归导出文件夹内的所有内容
+ /// 导出是否成功
+ private static bool ExportUnityPackage(
+ string[] assetPaths,
+ string outputPath,
+ string[] ignorePatterns = null,
+ bool includeDependencies = true,
+ bool recurseFolders = true
+ )
+ {
+ // 1. 验证资源路径
+ if (!ValidateAssetPaths(assetPaths))
+ {
+ Debug.LogError("导出失败:无效的资源路径");
+ return false;
+ }
+
+ // 2. 验证输出路径
+ if (!ValidateAndPrepareOutputPath(outputPath))
+ {
+ Debug.LogError("导出失败:无效的输出路径");
+ return false;
+ }
+
+ try
+ {
+ // 3. 处理需要导出的路径(过滤掉需要忽略的文件)
+ var temp = ProcessAssetPaths(assetPaths, ignorePatterns, recurseFolders);
+
+ var filteredPaths = temp.Where(File.Exists).ToArray();
+
+ if (filteredPaths.Length == 0)
+ {
+ Debug.LogError("导出失败:所有路径都被过滤掉了");
+ return false;
+ }
+
+ // 4. 构建导出选项
+ ExportPackageOptions options = ExportPackageOptions.Default;
+
+ // 如果需要递归文件夹,添加 Recurse 选项
+ if (recurseFolders)
+ {
+ options |= ExportPackageOptions.Recurse;
+ }
+
+ // 如果需要包含依赖资源,添加 IncludeDependencies 选项
+ if (includeDependencies)
+ {
+ options |= ExportPackageOptions.IncludeDependencies;
+ }
+
+ // 5. 执行导出
+ AssetDatabase.ExportPackage(filteredPaths, outputPath, options);
+
+ // 6. 验证结果
+ if (File.Exists(outputPath))
+ {
+ Debug.Log($"导出成功:{outputPath}");
+ return true;
+ }
+
+ Debug.LogError("导出失败:文件未生成");
+ return false;
+ }
+ catch (Exception ex)
+ {
+ Debug.LogError($"导出异常:{ex.Message}");
+ return false;
+ }
+ }
+
+ ///
+ /// 处理资源路径,过滤掉需要忽略的文件
+ ///
+ private static string[] ProcessAssetPaths(string[] assetPaths, string[] ignorePatterns, bool recurseFolders)
+ {
+ if (ignorePatterns == null || ignorePatterns.Length == 0)
+ {
+ return assetPaths; // 没有需要忽略的模式,直接返回原路径
+ }
+
+ // 收集所有需要导出的文件路径
+ var allFiles = new System.Collections.Generic.List();
+
+ foreach (var path in assetPaths)
+ {
+ if (AssetDatabase.IsValidFolder(path))
+ {
+ // 如果是文件夹,获取所有文件
+ var filesInFolder = AssetDatabase.FindAssets("", new[] { path })
+ .Select(AssetDatabase.GUIDToAssetPath)
+ .ToArray();
+
+ // 根据递归选项和忽略模式过滤文件
+ allFiles.AddRange(filesInFolder.Where(file => !ShouldIgnore(file, ignorePatterns) && (recurseFolders || Path.GetDirectoryName(file) == path)));
+ var googleMobileAdsAndroidLib = Directory.GetDirectories(path, "GoogleMobileAdsPlugin", SearchOption.AllDirectories)
+ .Where(p => p.Replace("\\", "/").StartsWith("Assets/"))
+ .Select(p => p.Replace("\\", "/"))
+ .ToArray();
+ Debug.Log("yangwu firebase:"+googleMobileAdsAndroidLib);
+ allFiles.AddRange(googleMobileAdsAndroidLib);
+ }
+ else if (File.Exists(path))
+ {
+ // 如果是文件,检查是否需要忽略
+ if (!ShouldIgnore(path, ignorePatterns))
+ {
+ allFiles.Add(path);
+ }
+ }
+ var androidLibs = Directory.GetDirectories(path, "GoogleMobileAdsPlugin.androidlib", SearchOption.AllDirectories)
+ .Where(p => p.Replace("\\", "/").StartsWith("Assets/"))
+ .Select(p => p.Replace("\\", "/"))
+ .ToArray();
+ allFiles.AddRange(androidLibs);
+
+ }
+
+ return allFiles.Distinct().ToArray();
+ }
+
+ ///
+ /// 检查文件是否应该被忽略
+ ///
+ private static bool ShouldIgnore(string filePath, string[] ignorePatterns)
+ {
+ if (!ignorePatterns.Any(pattern => filePath.Contains(pattern) ||
+ Path.GetFileName(filePath).Contains(pattern) ||
+ (pattern.Contains("*") && MatchesWildcard(filePath, pattern)))) return false;
+ Debug.Log("ShouldIgnore true: " + filePath);
+ return true;
+ }
+
+ ///
+ /// 检查文件路径是否匹配通配符模式(使用正则表达式实现)
+ ///
+ private static bool MatchesWildcard(string filePath, string pattern)
+ {
+ try
+ {
+ // 将通配符模式转换为正则表达式
+ var regexPattern = "^" + Regex.Escape(pattern).Replace("\\*", ".*").Replace("\\?", ".") + "$";
+ var regex = new Regex(regexPattern, RegexOptions.IgnoreCase);
+
+ // 检查文件名和完整路径是否匹配
+ return regex.IsMatch(Path.GetFileName(filePath)) || regex.IsMatch(filePath);
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ // 以下为辅助方法
+ private static bool ValidateAssetPaths(string[] assetPaths)
+ {
+ if (assetPaths == null || assetPaths.Length == 0)
+ {
+ Debug.LogWarning("未指定任何资源路径");
+ return false;
+ }
+ foreach (var path in assetPaths)
+ {
+ if (string.IsNullOrWhiteSpace(path) || !path.StartsWith("Assets/"))
+ {
+ Debug.LogWarning($"无效路径格式:{path}(必须以 Assets/ 开头)");
+ return false;
+ }
+
+ if (AssetDatabase.IsValidFolder(path) || File.Exists(path)) continue;
+ Debug.LogWarning($"路径不存在:{path}");
+ return false;
+ }
+
+ return true;
+ }
+
+ private static bool ValidateAndPrepareOutputPath(string outputPath)
+ {
+ if (string.IsNullOrWhiteSpace(outputPath) || !outputPath.EndsWith(".unitypackage"))
+ {
+ Debug.LogWarning("输出路径必须包含 .unitypackage 扩展名");
+ return false;
+ }
+
+ var directory = Path.GetDirectoryName(outputPath);
+ if (Directory.Exists(directory)) return true;
+ try
+ {
+ if (directory == null)
+ {
+ return false;
+ }
+
+ Directory.CreateDirectory(directory);
+ }
+ catch (Exception ex)
+ {
+ Debug.LogError($"无法创建目录:{ex.Message}");
+ return false;
+ }
+
+ return true;
+ }
+
+ // ------------------------------
+ // 快捷导出示例(可直接在菜单调用)
+ // ------------------------------
+ [MenuItem("Tools/Export UnityPackage")]
+ public static void ExportExamplePackage()
+ {
+ var pathsToExport = new[]
+ {
+ "Assets/Adjust",
+ "Assets/BigoAds",
+ "Assets/BigoSDK",
+ "Assets/Editor",
+ "Assets/Editor Default Resources",
+ "Assets/ExternalDependencyManager",
+ "Assets/EFSDK",
+ "Assets/Firebase",
+ "Assets/GeneratedLocalRepo",
+ "Assets/GoogleMobileAds",
+ "Assets/KwaiAds",
+ "Assets/MaxSdk",
+ "Assets/Plugins",
+ "Assets/Script",
+ "Assets/ThinkingAnalytics",
+ "Assets/ThinkupTpnPlugin",
+ "Assets/UnityPackages"
+ };
+
+ // 定义需要忽略的文件/文件夹模式
+ var ignorePatterns = new[]
+ {
+ "Assets/Plugins/Android/AndroidManifest.xml",
+ "Assets/Plugins/Android/baseProjectTemplate.gradle",
+ "Assets/Plugins/Android/gradleTemplate.properties",
+ "Assets/Plugins/Android/LauncherManifest.xml",
+ "Assets/Plugins/Android/launcherTemplate.gradle",
+ "Assets/Plugins/Android/mainTemplate.gradle",
+ "Assets/Plugins/Android/MessagingUnityPlayerActivity.java",
+ "Assets/Plugins/Android/settingsTemplate.gradle",
+ };
+
+ // 获取项目根目录(Assets文件夹的上级目录)
+ var projectRoot = Path.GetFullPath(Path.Combine(Application.dataPath, ".."));
+
+ var outputPath = Path.Combine(projectRoot, $"RushSDK_{RushSDKManager.GetSDKVersion()}_{DateTime.Now:yyyyMMdd_HHmmss}.unitypackage");
+
+ // 执行导出(不包含依赖,使用我们定义的忽略模式)
+ ExportUnityPackage(pathsToExport, outputPath, ignorePatterns, includeDependencies: false);
+ }
+ }
\ No newline at end of file
diff --git a/Assets/Editor/PackageExporter.cs.meta b/Assets/Editor/PackageExporter.cs.meta
new file mode 100644
index 0000000..084df16
--- /dev/null
+++ b/Assets/Editor/PackageExporter.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f63a53a7744c14d5a9c6a3a3f0e36524
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/StreamingAssets/google-services-desktop.json.meta b/Assets/StreamingAssets/google-services-desktop.json.meta
index ef9c43e..52ff557 100644
--- a/Assets/StreamingAssets/google-services-desktop.json.meta
+++ b/Assets/StreamingAssets/google-services-desktop.json.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 35de05bb934f64861beae2647b59f730
+guid: 9074cef3c9d994f619d5ae12dea4e19c
DefaultImporter:
externalObjects: {}
userData:
diff --git a/UserSettings/Layouts/default-2022.dwlt b/UserSettings/Layouts/default-2022.dwlt
index 6144cba..db41fe3 100644
--- a/UserSettings/Layouts/default-2022.dwlt
+++ b/UserSettings/Layouts/default-2022.dwlt
@@ -141,7 +141,7 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 0
- width: 831
+ width: 978
height: 841
m_MinSize: {x: 100, y: 100}
m_MaxSize: {x: 8096, y: 16192}
@@ -165,8 +165,8 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 0
- width: 831
- height: 185.5
+ width: 978
+ height: 319.5
m_MinSize: {x: 201, y: 221}
m_MaxSize: {x: 4001, y: 4021}
m_ActualView: {fileID: 12}
@@ -191,9 +191,9 @@ MonoBehaviour:
m_Position:
serializedVersion: 2
x: 0
- y: 185.5
- width: 831
- height: 655.5
+ y: 319.5
+ width: 978
+ height: 521.5
m_MinSize: {x: 231, y: 271}
m_MaxSize: {x: 10001, y: 10021}
m_ActualView: {fileID: 14}
@@ -217,9 +217,9 @@ MonoBehaviour:
m_Children: []
m_Position:
serializedVersion: 2
- x: 831
+ x: 978
y: 0
- width: 212
+ width: 176
height: 841
m_MinSize: {x: 202, y: 221}
m_MaxSize: {x: 4002, y: 4021}
@@ -243,9 +243,9 @@ MonoBehaviour:
m_Children: []
m_Position:
serializedVersion: 2
- x: 1043
+ x: 1154
y: 0
- width: 427
+ width: 316
height: 841
m_MinSize: {x: 641, y: 601}
m_MaxSize: {x: 4001, y: 4021}
@@ -296,7 +296,7 @@ MonoBehaviour:
m_CachedPref: 226
m_ControlHash: -371814159
m_PrefName: Preview_InspectorPreview
- m_LastInspectedObjectInstanceID: -1
+ m_LastInspectedObjectInstanceID: 22576
m_LastVerticalScrollValue: 0
m_GlobalObjectId:
m_InspectorMode: 0
@@ -325,8 +325,8 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 95
- width: 830
- height: 164.5
+ width: 977
+ height: 298.5
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
@@ -1014,9 +1014,9 @@ MonoBehaviour:
m_Pos:
serializedVersion: 2
x: 0
- y: 280.5
- width: 830
- height: 634.5
+ y: 414.5
+ width: 977
+ height: 500.5
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
@@ -1038,26 +1038,7 @@ MonoBehaviour:
m_SkipHidden: 0
m_SearchArea: 1
m_Folders:
- - Assets/Adjust
- - Assets/BigoAds
- - Assets/BigoSDK
- - Assets/Editor
- - Assets/Editor Default Resources
- - Assets/EFSDK
- - Assets/ExternalDependencyManager
- - Assets/Firebase
- - Assets/GeneratedLocalRepo
- - Assets/GoogleMobileAds
- - Assets/KwaiAds
- - Assets/MaxSdk
- - Assets/Plugins
- - Assets/Resources
- - Assets/Scenes
- - Assets/Script
- - Assets/StreamingAssets
- - Assets/ThinkingAnalytics
- - Assets/ThinkupTpnPlugin
- - Assets/UnityPackages
+ - Assets/Plugins/Android
m_Globs: []
m_OriginalText:
m_ImportLogFlags: 0
@@ -1073,7 +1054,7 @@ MonoBehaviour:
scrollPos: {x: 0, y: 0}
m_SelectedIDs: da400000
m_LastClickedID: 16602
- m_ExpandedIDs: 00000000846c0000866c0000886c00008a6c00008c6c00008e6c0000906c0000926c0000946c0000966c0000986c00009a6c00009c6c00009e6c0000a06c0000a26c0000a46c0000a66c0000a86c0000aa6c0000ac6c0000ae6c0000
+ m_ExpandedIDs:
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name:
@@ -1098,10 +1079,10 @@ MonoBehaviour:
m_Icon: {fileID: 0}
m_ResourceFile:
m_AssetTreeState:
- scrollPos: {x: 0, y: 0}
+ scrollPos: {x: 0, y: 113.99658}
m_SelectedIDs:
m_LastClickedID: 0
- m_ExpandedIDs: ffffffff00000000846c0000866c0000886c00008a6c00008c6c00008e6c0000906c0000926c0000946c0000966c0000986c00009a6c00009e6c0000a06c0000a26c0000a46c0000a66c0000a86c0000aa6c0000ac6c0000ae6c0000
+ m_ExpandedIDs: ffffffff0000000064410000dc4100008c420000
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name:
@@ -1153,7 +1134,7 @@ MonoBehaviour:
m_Icon: {fileID: 0}
m_ResourceFile:
m_NewAssetIndexInList: -1
- m_ScrollPosition: {x: 0, y: 0}
+ m_ScrollPosition: {x: 0, y: 186.5}
m_GridSize: 16
m_SkipHiddenPackages: 0
m_DirectoriesAreaWidth: 82
@@ -1178,9 +1159,9 @@ MonoBehaviour:
m_Pos:
serializedVersion: 2
x: 0
- y: 280.5
- width: 611
- height: 634.5
+ y: 414.5
+ width: 977
+ height: 500.5
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
@@ -1211,9 +1192,9 @@ MonoBehaviour:
m_Tooltip:
m_Pos:
serializedVersion: 2
- x: 831
+ x: 978
y: 95
- width: 210
+ width: 174
height: 820
m_SerializedDataModeController:
m_DataMode: 0
@@ -1228,9 +1209,9 @@ MonoBehaviour:
m_SceneHierarchy:
m_TreeViewState:
scrollPos: {x: 0, y: 0}
- m_SelectedIDs: 2a6d00002c6d00002e6d0000306d0000326d0000346d0000366d0000386d00003a6d00003c6d00003e6d0000406d0000426d0000446d0000466d00009c6c00006a6d00006c6d00006e6d0000706d0000
+ m_SelectedIDs: 30580000
m_LastClickedID: 0
- m_ExpandedIDs: 2efbffff
+ m_ExpandedIDs: 48c1feff
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name:
@@ -1274,9 +1255,9 @@ MonoBehaviour:
m_Tooltip:
m_Pos:
serializedVersion: 2
- x: 1043
+ x: 1154
y: 95
- width: 426
+ width: 315
height: 820
m_SerializedDataModeController:
m_DataMode: 0