using System; using System.Collections.Generic; using System.IO; using UnityEditor; using UnityEngine; #pragma warning disable class ProjectBuildService : Editor { #region 参数解析 public static string ChannelName { get { #if UNITY_ANDROID //这里遍历所有参数,找到 ChannelName 开头的参数, 然后把-符号 后面的字符串返回, foreach (string arg in Environment.GetCommandLineArgs()) { if (arg.StartsWith("ChannelName")) { return arg.Split("-"[0])[1]; } } return "Android"; #elif UNITY_IOS return "IOS"; #else return "General"; #endif } } public static string ExportPath { get { string path = Application.dataPath; //这里遍历所有参数,找到 ExportPath 开头的参数, 然后把-符号 后面的字符串返回, foreach (string arg in Environment.GetCommandLineArgs()) { if (arg.StartsWith("ExportPath")) { path = arg.Split("-"[0])[1]; } } #if UNITY_WEBGL return path + "/" + ApplicationMode; #elif UNITY_IOS return path += "/" + ChannelName + "/" + ApplicationMode; #else return path += "/" + ChannelName + "/" + ApplicationMode + "/"; #endif } } public static AppMode ApplicationMode { get { //这里遍历所有参数,找到 AppMpde 开头的参数, 然后把-符号 后面的字符串返回, foreach (string arg in Environment.GetCommandLineArgs()) { if (arg.StartsWith("AppMode")) { return (AppMode)Enum.Parse(typeof(AppMode), arg.Split("-"[0])[1]); } } return AppMode.Developing; } } public static bool IsUseAssetsBundle { get { //这里遍历所有参数,找到 UseAssetsBundle 开头的参数, 然后把-符号 后面的字符串返回, foreach (string arg in Environment.GetCommandLineArgs()) { if (arg.StartsWith("UseAssetsBundle")) { return bool.Parse(arg.Split("-"[0])[1]); } } return false; } } public static bool IsUseLua { get { //这里遍历所有参数,找到 UseLua 开头的参数, 然后把-符号 后面的字符串返回, foreach (string arg in Environment.GetCommandLineArgs()) { if (arg.StartsWith("UseLua")) { return bool.Parse(arg.Split("-"[0])[1]); } } return false; } } public static string Version { get { return Application.version + "." + VersionService.LargeVersion + "." + VersionService.SmallVersion; } } #endregion #region 打包函数 #region 通用 static void PrintDebug() { string debugString = ""; debugString += ">>>============================================================自动打包输出============================================================<<<\n"; foreach (string arg in Environment.GetCommandLineArgs()) { debugString += "参数:" + arg + "\n"; } debugString += "\n"; debugString += "是否使用 Bundle 打包: " + IsUseAssetsBundle + "\n"; debugString += "是否使用 Lua : " + IsUseLua + "\n"; debugString += "渠道名: " + ChannelName + "\n"; debugString += "发布模式: " + ApplicationMode + "\n"; debugString += "导出路径: " + ExportPath + "\n"; debugString += ">>>====================================================================================================================================<<<\n"; Debug.Log(debugString); } static void SetApplicationMode(AppMode mode) { string appModeDefine = ""; switch (mode) { case AppMode.Developing: appModeDefine = "APPMODE_DEV"; break; case AppMode.QA: appModeDefine = "APPMODE_QA"; break; case AppMode.Release: appModeDefine = "APPMODE_REL"; break; } AddScriptDefine(appModeDefine); } static void SetLua(bool useLua) { if (useLua) { AddScriptDefine("USE_LUA"); } } /// /// 切换渠道 /// static void ChangeChannel(string channelName) { #if UNITY_ANDROID SchemeDataService.ChangeScheme(channelName); #endif } /// ///打包或者使用Bundle流程 /// static void UseResourcesOrBundle(bool useBundle) { if (useBundle) { AddScriptDefine("USE_BUNDLE"); BundlePackage(); #if UNITY_IOS //删除_Res和_Doc FileTool.SafeDeleteDirectory(Application.dataPath + "/_Res"); FileTool.SafeDeleteDirectory(Application.dataPath + "/_Doc"); #endif } else { if (Directory.Exists(Application.dataPath + "/StreamingAssets")) { //不使用 Bundle 则删除 StreamingAssets 文件夹 FileTool.SafeDeleteDirectory(Application.dataPath + "/StreamingAssets"); } } } static void BundlePackage() { //自动增加小版本号 VersionService.SmallVersion++; VersionService.CreateVersionFile(); //打Bundle包 PackageService.Package(PackageEditorConfigService.RelyPackages, PackageEditorConfigService.Bundles); //删除 Resources 文件夹 FileTool.SafeDeleteDirectory(Application.dataPath + "/Resources"); } #endregion #region Android static void BuildForAndroid() { SwitchPlatform(BuildTarget.Android); //输出日志 PrintDebug(); //使用Lua SetLua(IsUseLua); //发布模式 SetApplicationMode(ApplicationMode); //使用Resource或者使用Bundle UseResourcesOrBundle(IsUseAssetsBundle); //切换渠道 ChangeChannel(ChannelName); //设置编译指令 ApplyScriptDefine(); //设置签名 //签名路径 PlayerSettings.Android.keystoreName = ""; //密钥密码 PlayerSettings.Android.keystorePass = ""; //密钥别名 PlayerSettings.Android.keyaliasName = ""; //别名密码 PlayerSettings.Android.keyaliasPass = ""; //打包 string path = ExportPath + "/" + GetPackageName() + ".apk"; #if UNITY_2017_1_OR_NEWER BuildPlayerOptions bo = new BuildPlayerOptions(); bo.scenes = GetBuildScenes(); bo.target = BuildTarget.Android; bo.options = BuildOptions.None; bo.locationPathName = path; BuildPipeline.BuildPlayer(bo); #else BuildOptions option = BuildOptions.None; if (ApplicationMode == AppMode.Release) { option = BuildOptions.Il2CPP; } BuildPipeline.BuildPlayer(GetBuildScenes(), path, BuildTarget.Android, option); #endif } #endregion #region IOS static void BuildForIOS() { SwitchPlatform(BuildTarget.iOS); //输出日志 PrintDebug(); //使用Lua SetLua(IsUseLua); //发布模式 SetApplicationMode(ApplicationMode); //使用Resource或者使用Bundle UseResourcesOrBundle(IsUseAssetsBundle); //切换渠道 ChangeChannel(ChannelName); //设置编译指令 ApplyScriptDefine(); //打包 #if UNITY_2017_1_OR_NEWER BuildPlayerOptions bo = new BuildPlayerOptions(); bo.scenes = GetBuildScenes(); bo.target = BuildTarget.iOS; bo.options = BuildOptions.None; bo.locationPathName = ExportPath; BuildPipeline.BuildPlayer(bo); #else BuildOptions option = BuildOptions.None; if (ApplicationMode == AppMode.Release) { option = BuildOptions.Il2CPP; } BuildPipeline.BuildPlayer(GetBuildScenes(), ExportPath, BuildTarget.iOS, option); #endif } #endregion #region WEBGL static void BuildForWEBGL() { SwitchPlatform(BuildTarget.WebGL); //输出日志 PrintDebug(); //使用Lua SetLua(IsUseLua); //发布模式 SetApplicationMode(ApplicationMode); //使用Resource或者使用Bundle UseResourcesOrBundle(IsUseAssetsBundle); //切换渠道 ChangeChannel(ChannelName); //设置编译指令 ApplyScriptDefine(); //打包 BuildOptions option = BuildOptions.None; if (ApplicationMode != AppMode.Release) { option = BuildOptions.Development; } BuildPipeline.BuildPlayer(GetBuildScenes(), ExportPath, BuildTarget.WebGL, option); } #endregion #endregion #region 功能函数 //在这里找出你当前工程所有的场景文件,假设你只想把部分的scene文件打包 那么这里可以写你的条件判断 总之返回一个字符串数组。 static string[] GetBuildScenes() { List names = new List(); foreach (EditorBuildSettingsScene e in EditorBuildSettings.scenes) { if (e == null) continue; if (e.enabled) names.Add(e.path); } return names.ToArray(); } static string GetPackageName() { #if UNITY_WEBGL return Application.productName; #else return Application.productName + "_" + Version + "_"+ ChannelName + "_" + GetModeName(ApplicationMode) +"_"+ GetTimeString(); #endif } static string GetTimeString() { DateTime date = DateTime.Now; return date.Year + string.Format("{0:d2}", date.Month) + string.Format("{0:d2}", date.Day) + "_" + string.Format("{0:d2}", date.Hour) + string.Format("{0:d2}", date.Minute); } static string GetModeName(AppMode mode) { switch (mode) { case AppMode.Developing: return "Dev"; ; case AppMode.QA: return "QA"; ; case AppMode.Release: return "Rel"; ; default: return "unknow"; } } public static void SetScriptDefine(string symbols) { BuildTargetGroup targetGroup = BuildTargetGroup.Unknown; #if UNITY_ANDROID targetGroup = BuildTargetGroup.Android; #elif UNITY_IOS targetGroup = BuildTargetGroup.iOS; #endif string define = PlayerSettings.GetScriptingDefineSymbolsForGroup(targetGroup); if (!define.Contains(symbols)) { define += ";" + symbols; } PlayerSettings.SetScriptingDefineSymbolsForGroup(targetGroup, define); } static List s_defines = new List(); static void AddScriptDefine(string symbols) { if(!s_defines.Contains(symbols)) { s_defines.Add(symbols); } } static void ApplyScriptDefine() { BuildTargetGroup targetGroup = BuildTargetGroup.Unknown; #if UNITY_ANDROID targetGroup = BuildTargetGroup.Android; #elif UNITY_IOS targetGroup = BuildTargetGroup.iOS; #elif UNITY_WEBGL targetGroup = BuildTargetGroup.WebGL; #endif string define = PlayerSettings.GetScriptingDefineSymbolsForGroup(targetGroup); for (int i = 0; i < s_defines.Count; i++) { if(!define.Contains(s_defines[i])) { define += ";" + s_defines[i]; } } PlayerSettings.SetScriptingDefineSymbolsForGroup(targetGroup, define); } /// /// 切换平台 /// /// public static void SwitchPlatform(BuildTarget target) { if (EditorUserBuildSettings.activeBuildTarget != target) { EditorUserBuildSettings.SwitchActiveBuildTarget(target); } } #endregion }