using UnityEngine; using UnityEditor; using UnityEditor.Callbacks; using System.Collections.Generic; using DeployMethod = System.Reflection.MethodInfo; namespace UltraCombos { public enum Drive { A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z }; public sealed class Utils { public static string[] ConvertEditorBuildSettingsScenesToPaths(EditorBuildSettingsScene[] scenes) { List lst_scene_path = new List(); foreach (EditorBuildSettingsScene scene in scenes) { lst_scene_path.Add(scene.path); } return lst_scene_path.ToArray(); } public static EditorBuildSettingsScene[] ConvertPathsToEditorBuildSettingsScenes(string[] paths) { List lst_editor_build_settings_scene = new List(); foreach (string path in paths) { lst_editor_build_settings_scene.Add(new EditorBuildSettingsScene(path, true)); } return lst_editor_build_settings_scene.ToArray(); } public static string GetProjectPath() { return System.IO.Directory.GetParent(UnityEngine.Application.dataPath).ToString(); } public static void SplitPath(string full_path, out string parent_path, out string filename) { parent_path = System.IO.Path.GetDirectoryName(full_path).Replace("\\", "/"); if (parent_path.Length == 0) { parent_path = "/"; } if (parent_path[parent_path.Length - 1] != '/') { parent_path += "/"; } filename = System.IO.Path.GetFileName(full_path); } public static string MakeRelativePath(string workingDirectory, string fullPath) { string result = string.Empty; int offset; // this is the easy case. The file is inside of the working directory. if (fullPath.StartsWith(workingDirectory)) { return fullPath.Substring(workingDirectory.Length + 1); } // the hard case has to back out of the working directory string[] baseDirs = workingDirectory.Split(new char[] { ':', '\\', '/' }); string[] fileDirs = fullPath.Split(new char[] { ':', '\\', '/' }); // if we failed to split (empty strings?) or the drive letter does not match if (baseDirs.Length <= 0 || fileDirs.Length <= 0 || baseDirs[0] != fileDirs[0]) { // can't create a relative path between separate harddrives/partitions. return fullPath; } // skip all leading directories that match for (offset = 1; offset < baseDirs.Length; offset++) { if (baseDirs[offset] != fileDirs[offset]) break; } // back out of the working directory for (int i = 0; i < (baseDirs.Length - offset); i++) { result += "..\\"; } // step into the file path for (int i = offset; i < fileDirs.Length - 1; i++) { result += fileDirs[i] + "\\"; } // append the file result += fileDirs[fileDirs.Length - 1]; return result.Replace("\\", "/"); } public static int Xcopy(string src, string dst, string args) { string pathsrc = src.Replace('/', '\\'); string pathdst = dst.Replace('/', '\\'); System.Diagnostics.Process p = System.Diagnostics.Process.Start("xcopy.exe", pathsrc + " " + pathdst + " " + args); p.WaitForExit(); return p.ExitCode; } public static string GetDriveName(Drive d) { //switch (d) //{ // case Drive.A: return "A:"; // case Drive.B: return "B:"; // case Drive.C: return "C:"; // case Drive.D: return "D:"; // case Drive.E: return "E:"; // case Drive.F: return "F:"; // case Drive.G: return "G:"; // case Drive.H: return "H:"; // case Drive.I: return "I:"; // case Drive.J: return "J:"; // case Drive.K: return "K:"; // case Drive.L: return "L:"; // case Drive.M: return "M:"; // case Drive.N: return "N:"; // case Drive.O: return "O:"; // case Drive.P: return "P:"; // case Drive.Q: return "Q:"; // case Drive.R: return "R:"; // case Drive.S: return "S:"; // case Drive.T: return "T:"; // case Drive.U: return "U:"; // case Drive.V: return "V:"; // case Drive.W: return "W:"; // case Drive.X: return "X:"; // case Drive.Y: return "Y:"; // case Drive.Z: return "Z:"; //} return d + ":"; } } public sealed class NetDrive { public sealed class ConnInfo { public string m_username; public string m_password; public string m_netpath; } public static int Connect(Drive d, ConnInfo info) { string netpath = info.m_netpath.Replace('/', '\\'); string args = "use"; args += " " + Utils.GetDriveName(d); args += " " + netpath; if (info.m_password.Length > 0) { args += " " + info.m_password; } if (info.m_username.Length > 0) { args += " /user:" + info.m_username; } System.Diagnostics.Process p = System.Diagnostics.Process.Start("net.exe", args); p.WaitForExit(); return p.ExitCode; } public static int Disconnect(Drive d) { string args = "use"; args += " " + Utils.GetDriveName(d); args += " /delete"; System.Diagnostics.Process p = System.Diagnostics.Process.Start("net.exe", args); p.WaitForExit(); return p.ExitCode; } } public sealed class DepolyCommandParser { public static List GetScenePathList(string[] args) { return sf_GetArgs(args, "--scene"); } public static string GetBuildInfoJsonFilename(string[] args) { List lst = sf_GetArgs(args, "--build-info-json"); if (lst.Count == 0) { return ""; } return lst[0]; } public static List GetPreExeMethodtList(string[] args) { List lst_method = new List(); List lst = sf_GetArgs(args, "--pre-execute-method"); foreach(string arg in lst) { DeployMethod method = sf_ConvertToDeployMethod(arg); if (method == null) { continue; } lst_method.Add(method); } return lst_method; } public static List GetPostExeMethodList(string[] args) { List lst_method = new List(); List lst = sf_GetArgs(args, "--post-execute-method"); foreach (string arg in lst) { DeployMethod method = sf_ConvertToDeployMethod(arg); if (method == null) { continue; } lst_method.Add(method); } return lst_method; } /////////////////////////////////////////////////////////////////////////////////////// //Must be [class.method] private static DeployMethod sf_ConvertToDeployMethod(string arg) { char[] delimiter_chars = { '.' }; string[] words = arg.Split(delimiter_chars); if (words.Length != 2) { return null; } System.Type type = System.Type.GetType(words[0]); if (type == null) { return null; } DeployMethod method = type.GetMethod(words[1]); return method; } private static List sf_GetArgs(string[] args, string cmd) { string cmd_lst_bgn = cmd + "-begin"; string cmd_lst_end = cmd + "-end"; List lst_args = new List(); bool is_lst_began = false; bool is_one_arg = false; foreach (string arg in args) { if (string.Compare(arg, cmd) == 0) { is_one_arg = true; continue; } else if (string.Compare(arg, cmd_lst_bgn) == 0) { is_one_arg = false; is_lst_began = true; continue; } else if (is_lst_began && string.Compare(arg, cmd_lst_end) == 0) { is_lst_began = false; continue; } if (!is_lst_began && !is_one_arg) { continue; } lst_args.Add(arg); is_one_arg = false; } return lst_args; } } } public class BuildBatchInfo { public string platform; public string build_path; public string filename; public string[] scenes; public bool neeed_open_the_folder_when_sccuess; public bool need_silent_crashes; } public sealed class ucDeploy { [PostProcessBuildAttribute(1)] public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject) { if (s_scenes_tmp == null) { return; } string[] args = System.Environment.GetCommandLineArgs(); List lst_post_method = UltraCombos.DepolyCommandParser.GetPostExeMethodList(args); foreach (DeployMethod method in lst_post_method) { switch (method.GetParameters().Length) { case 0: method.Invoke(null, null); break; case 1: method.Invoke(null, new object[] { target }); break; default: case 2: method.Invoke(null, new object[] { target, pathToBuiltProject }); break; } } EditorBuildSettings.scenes = s_scenes_tmp; s_scenes_tmp = null; if (ucDeployTool.NeedBatch(target)) { ucDeployTool.CreateBatchFileAndHideTheExe(pathToBuiltProject, s_need_slient_crashes_tmp); } } [System.Obsolete("ucDeploy.Execute is deprecated, please use ucDeploy.Execute2 instead.")] public static void Execute() { string[] args = System.Environment.GetCommandLineArgs(); List lst_scene_path = UltraCombos.DepolyCommandParser.GetScenePathList(args); List lst_editor_build_settings_scene = new List(); List lst_pre_method = UltraCombos.DepolyCommandParser.GetPreExeMethodtList(args); foreach (string path in lst_scene_path) { lst_editor_build_settings_scene.Add(new EditorBuildSettingsScene(path, true)); UnityEngine.Debug.Log("====================== [78 Log] Added Scene Path: " + path + " ======================"); } s_scenes_tmp = EditorBuildSettings.scenes; EditorBuildSettings.scenes = lst_editor_build_settings_scene.ToArray(); foreach (DeployMethod method in lst_pre_method) { method.Invoke(null, null); } } public static void Execute2() { string[] args = System.Environment.GetCommandLineArgs(); List lst_pre_method = UltraCombos.DepolyCommandParser.GetPreExeMethodtList(args); string json_filename = UltraCombos.DepolyCommandParser.GetBuildInfoJsonFilename(args); if (json_filename == "") { sf_Error("Can not find the json file, please check the arg: --build-info-json ."); return; } string json = System.IO.File.ReadAllText(json_filename); BuildBatchInfo info; try { info = UnityEngine.JsonUtility.FromJson(json); } catch (System.Exception exception) { sf_Error(json_filename + " is invalid, " + exception.Message); return; } if (info == null) { sf_Error(json_filename + " is invalid."); return; } BuildTarget target; try { target = (BuildTarget)System.Enum.Parse(typeof(BuildTarget), info.platform); } catch (System.Exception exception) { sf_Error(json_filename + " - platform is invalid: " + info.platform + " ," + exception.Message); return; } if (info.build_path == "") { sf_Error(json_filename + " - build_path is invalid."); return; } if (info.filename == "") { sf_Error(json_filename + "- filename is invalid."); return; } if (info.scenes == null || info.scenes.Length == 0) { sf_Error(json_filename + "- scenes is invalid."); return; } foreach (DeployMethod method in lst_pre_method) { method.Invoke(null, null); } s_scenes_tmp = EditorBuildSettings.scenes; s_need_slient_crashes_tmp = info.need_silent_crashes; string path = info.build_path + info.filename; bool yes = ucDeployTool.Deploy(path, target, info.scenes); if (!yes) { sf_Error("build failed. Noooo> Orz"); } else { if (info.neeed_open_the_folder_when_sccuess) { ucDeployTool.OpenTheFolder(path); } } } private static void sf_Error(string msg) { //string path_with_env = @"%USERPROFILE%\AppData\Local\Unity\Editor"; //string path_log = System.Environment.ExpandEnvironmentVariables(path_with_env); //ucDeployTool.OpenTheFolder(path_log); string error = "************************************************************************************************\n"; error += "[7878Error] " + msg + "\n"; error += "***********************************************************************************************************\n"; throw new System.Exception(error); } private static EditorBuildSettingsScene[] s_scenes_tmp; private static bool s_need_slient_crashes_tmp = true; } public sealed class ucDeployCustomExample { /*Added this function to menu item... */ // public static void Execute() { /* * //Select path . * string path = EditorUtility.SaveFolderPanel("Choose Location of Built Game", "", ""); */ string path = "C:/UC/Example/"; string exe_file = "78ester.exe"; string output_path = path + exe_file; string[] ary_scene_path = new string[] { "Assets/Tmp01.unity", "Assets/Tmp02.unity" }; // Build player. BuildPipeline.BuildPlayer(ary_scene_path, output_path, BuildTarget.StandaloneWindows64, BuildOptions.None); /* * //Copy a file from the project folder to the build folder, alongside the built game. * FileUtil.CopyFileOrDirectory("Assets/Templates/Readme.txt", path + "Readme.txt"); */ /* * //Run the game (Process class from System.Diagnostics). * Process proc = new Process(); * proc.StartInfo.FileName = output_path; * proc.Start(); */ } } public sealed class ucDeployTool { #if false [MenuItem("ucDeploy/Target/Win64", true)] public static bool CanSelectTargetPlatformWin64() { return s_target != BuildTarget.StandaloneWindows64; } [MenuItem("ucDeploy/Target/Win64", false, 0)] public static void SelectTargetPlatformWin64() { s_can_quick_deploy = false; s_target = BuildTarget.StandaloneWindows64; } [MenuItem("ucDeploy/Target/Win32", true)] public static bool CanSelectTargetPlatformWin32() { return s_target != BuildTarget.StandaloneWindows; } [MenuItem("ucDeploy/Target/Win32", false, 0)] public static void SelectTargetPlatformWin32() { s_can_quick_deploy = false; s_target = BuildTarget.StandaloneWindows; } [MenuItem("ucDeploy/Target/iOS", true)] public static bool CanSelectTargetPlatformiOS() { return s_target != BuildTarget.iOS; } [MenuItem("ucDeploy/Target/iOS", false, 0)] public static void SelectTargetPlatformiOS() { s_can_quick_deploy = false; s_target = BuildTarget.iOS; } [MenuItem("ucDeploy/Target/Android", true)] public static bool CanSelectTargetPlatformAndroid() { return s_target != BuildTarget.Android; } [MenuItem("ucDeploy/Target/Android", false, 0)] public static void SelectTargetPlatformAndroid() { s_can_quick_deploy = false; s_target = BuildTarget.Android; } /*Added this function to menu item... */ [MenuItem("ucDeploy/Deploy %F5", true)] public static bool CanDeploy() { return sf_CanDeploy(); } /*Added this function to menu item... */ [MenuItem("ucDeploy/Deploy %F5", false, 100)] public static void Deploy() { //Select path BuildTarget target = s_target; string path = SelectBuildPath(target, s_previous_build_path); if (path == "") { return; } // Build player. bool yes = Deploy(path, target, null); if (!yes) { return; } s_previous_build_path = path; s_can_quick_deploy = true; if (NeedBatch(target)) { CreateBatchFileAndHideTheExe(path); } if (s_auto_create_one_click_build_batch_when_deploy) { sf_CreateOneClickBuildBatchAfterDeploy(path); } } [MenuItem("ucDeploy/Tmp", false, 100)] public static void Tmp() { Shipper shipper = Shipper.GetShipper(); if (shipper != null) { shipper.Print(); } } [MenuItem("ucDeploy/Deploy Quickly _F5", true)] public static bool CanDeployQuickly() { return sf_CanDeploy() && s_can_quick_deploy; } [MenuItem("ucDeploy/Deploy Quickly _F5", false, 100)] public static void DeployQuickly() { BuildTarget target = s_target; string path = s_previous_build_path; bool yes = Deploy(path, target, null); if (!yes) { return; } if (NeedBatch(target)) { CreateBatchFileAndHideTheExe(path); } if (s_auto_create_one_click_build_batch_when_deploy) { sf_CreateOneClickBuildBatchAfterDeploy(path); } } [MenuItem("ucDeploy/Deploy Quickly And Run It %#F5", true)] public static bool CanDeployQuicklyAndRunIt() { return sf_CanDeploy() && s_can_quick_deploy && sf_CanRun(); } [MenuItem("ucDeploy/Deploy Quickly And Run It %#F5", false, 100)] public static void DeployQuicklyAndRunIt() { BuildTarget target = s_target; string path = s_previous_build_path; bool yes = Deploy(path, target, null); if (!yes) { return; } if (NeedBatch(target)) { CreateBatchFileAndHideTheExe(path); } if (s_auto_create_one_click_build_batch_when_deploy) { sf_CreateOneClickBuildBatchAfterDeploy(path); } //Run the game (Process class from System.Diagnostics). Run(path); } [MenuItem("ucDeploy/Open Deploy Folder _F6", false, 500)] public static void OpenDeployFolder() { bool yes = OpenTheFolder(s_previous_build_path); if (!yes) { EditorUtility.DisplayDialog("[Warning] Open Deploy Folder", "The folder is not exist", "Orz"); } } [MenuItem("ucDeploy/Create Batch File And Hide Execution File", false, 600)] public static void CreateBatchFileAndHideTheExe() { //Select path string path = EditorUtility.SaveFilePanel("Deploy", s_previous_build_path, "", "exe"); if (path == "") { return; } CreateBatchFileAndHideTheExe(path); } [MenuItem("ucDeploy/One Click Build Batch/Create %F7", true)] public static bool CanOneClickBuildBatch_Create() { return sf_CanDeploy(); } [MenuItem("ucDeploy/One Click Build Batch/Create %F7", false, 700)] public static void OneClickBuildBatch_Create() { string batch_path = EditorUtility.SaveFilePanel("Create Build Batch", "", s_previous_build_batch_filename, "bat"); if (batch_path == "") { return; } BuildTarget target = s_target; string build_path = SelectBuildPath(target, s_previous_build_path); if (build_path == "") { return; } sf_CreateOneClickBuildBatch(batch_path, target, build_path); s_previous_build_batch_filename = System.IO.Path.GetFileName(batch_path); } [MenuItem("ucDeploy/One Click Build Batch/Create Quickly _F7", true)] public static bool CanOneClickBuildBatchh_CreateQuickly() { return sf_CanDeploy() && s_can_quick_deploy; } [MenuItem("ucDeploy/One Click Build Batch/Create Quickly _F7", false, 700)] public static void OneClickBuildBatch_CreateQuickly() { string build_path = s_previous_build_path; string batch_path = s_previous_build_batch_filename; if (batch_path == "") { batch_path = "build_" + System.IO.Path.GetFileNameWithoutExtension(build_path) + ".bat"; s_previous_build_batch_filename = batch_path; } sf_CreateOneClickBuildBatch(batch_path, s_target, build_path); } [MenuItem("ucDeploy/One Click Build Batch/Auto Create When Deploy/On", true)] public static bool CanOneClickBuildBatch_AutoCreateWhenDeploy_On() { return !s_auto_create_one_click_build_batch_when_deploy; } [MenuItem("ucDeploy/One Click Build Batch/Auto Create When Deploy/On", false, 900)] public static void OneClickBuildBatch_AutoCreateWhenDeploy_On() { s_auto_create_one_click_build_batch_when_deploy = true; } [MenuItem("ucDeploy/One Click Build Batch/Auto Create When Deploy/Off", true)] public static bool CanOneClickBuildBatch_AutoCreateWhenDeploy_Off() { return s_auto_create_one_click_build_batch_when_deploy; } [MenuItem("ucDeploy/One Click Build Batch/Auto Create When Deploy/Off", false, 900)] public static void OneClickBuildBatch_AutoCreateWhenDeploy_Off() { s_auto_create_one_click_build_batch_when_deploy = false; } #endif //[MenuItem("ucDeploy/One Click Build Batch/Auto Create When Deploy/Off", false, 900)] //public static void OneClickBuildBatch_AutoCreateWhenDeploy_Off() //{ s_auto_create_one_click_build_batch_when_deploy = false; // //} [MenuItem("UltraCombos/Deploy Default _F5", true)] public static bool CanDeployDefaultFromShipper() { return Shipper.CanDeployDefault(); } [MenuItem("UltraCombos/Deploy Default _F5")] public static void DeployQuicklyFromShipper() { Shipper.DeployDefault(); } public static bool Deploy(string path, BuildTarget target, string[] scenes) { BuildPlayerOptions options = new BuildPlayerOptions(); options.locationPathName = path; options.target = target; options.scenes = scenes; options.options = BuildOptions.None; if (options.scenes == null) { options.scenes = EditorBuildSettingsScene.GetActiveSceneList(EditorBuildSettings.scenes); //UltraCombos.Utils.ConvertEditorBuildSettingsScenesToPaths(EditorBuildSettings.scenes); } // Build player. #if UNITY_2018_1_OR_NEWER string ret = BuildPipeline.BuildPlayer(options).ToString(); #else string ret = BuildPipeline.BuildPlayer(options); #endif if (ret == "") { return true; } EditorUtility.DisplayDialog("[Error] Deploy " + target, ret, "Orz"); return false; } public static bool NeedBatch(BuildTarget target) { return target == BuildTarget.StandaloneWindows64 || target == BuildTarget.StandaloneWindows; } public static void Run(string path) { System.Diagnostics.Process proc = new System.Diagnostics.Process(); proc.StartInfo.FileName = path; proc.Start(); } public static BuildTarget GetTarget() { return s_target; } public static string GetBuildPath() { return s_previous_build_path; } public static void CreateBatchFileAndHideTheExe(string exe_path, bool need_silent_crashes = true) { string exe_file = System.IO.Path.GetFileName(exe_path); string filename = System.IO.Path.GetFileNameWithoutExtension(exe_path); string data_folder = filename + "_Data"; string log_file_without_txt = "output_log"; string log_file = log_file_without_txt + ".txt"; string exe_path_var = need_silent_crashes? "\"%exe_path%\" -silent-crashes " : "\"%exe_path%\""; string[] batch_content = { "@ECHO OFF", "SETLOCAL EnableDelayedExpansion", "SET build_path=%~dp0", "SET data_path=%build_path%" + data_folder, "SET exe_path=%build_path%" + exe_file, "SET max_log_count=32", "SET /a log_count=0", "REM List all files in the " + data_folder + ", order sort by the latest date.", "FOR /f \"tokens=*\" %%a in ('dir %data_path% /b /o:-d') DO (", " REM Split the filename by '-'.", " FOR /f \"tokens=1 delims=-\" %%g IN (\"%%a\") DO (", " REM If first token is 'output_log', count it.", " IF %%g==output_log (", " SET /a log_count+=1", " REM If count is greater equal than max count, delete this log txt.", " IF !log_count! GEQ %max_log_count% DEL /f \"%data_path%\\%%a\"", " )", " )", ")", "REM Split the date by '/' and ' ', and then combine those token by '-'", "FOR /f \"tokens=1-3 delims=/ \" %%a IN (\"%date%\") DO (SET date_tmp=%%a-%%b-%%c)", "REM Split the time by '/' and ':', and then combine those token by '-'", "FOR /f \"tokens=1-3 delims=/:\" %%a IN (\"%time%\") DO (SET time_tmp=%%a-%%b-%%c)", "REM Remove all space character in the date_tmp.", "FOR %%# IN (\"%date_tmp%\") DO (", " SET var=%%~n#", " SET fmt_date=!var!", " SET fmt_date=!fmt_date: =!", ")", "REM Remove all space character in the time_tmp.", "FOR %%# IN (\"%time_tmp%\") DO (", " SET var=%%~n#", " SET fmt_time=!var!", " SET fmt_time=!fmt_time: =!", ")", "REM If output_log.txt is exist, copy it to new one with date and time.", "IF EXIST \"%data_path%\\" + log_file + "\" (", " COPY \"%data_path%\\" + log_file + "\" \"%data_path%\\" + log_file_without_txt + "-%fmt_date%-%fmt_time%.txt\"", ")", "START \"\" " + exe_path_var, }; string dir = System.IO.Path.GetDirectoryName(exe_path); string bat_path = System.IO.Path.Combine(dir, filename + ".bat"); System.IO.File.WriteAllLines(bat_path, batch_content); System.IO.File.SetAttributes(exe_path, System.IO.File.GetAttributes(exe_path) | System.IO.FileAttributes.Hidden); } public static bool OpenTheFolder(string path) { if (path == null || path == "") { return false; } string dir; do { bool yes = System.IO.Directory.Exists(path); if (yes) { dir = path; break; } dir = System.IO.Path.GetDirectoryName(path); if (dir == null || dir == "") { return false; } yes = System.IO.Directory.Exists(dir); if (!yes) { return false; } } while (false); System.Diagnostics.Process.Start(@dir); return true; } public static BuildBatchInfo CreateBuildBatchInfo(BuildTarget target, string build_path) { BuildBatchInfo info = new BuildBatchInfo(); info.platform = target.ToString(); info.build_path = System.IO.Path.GetDirectoryName(build_path) + "/"; info.filename = System.IO.Path.GetFileName(build_path); info.scenes = EditorBuildSettingsScene.GetActiveSceneList(EditorBuildSettings.scenes); //UltraCombos.Utils.ConvertEditorBuildSettingsScenesToPaths(EditorBuildSettings.scenes); info.neeed_open_the_folder_when_sccuess = true; info.need_silent_crashes = true; return info; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private static bool sf_CanRun() { BuildTarget target = s_target; return target == BuildTarget.StandaloneWindows64 || target == BuildTarget.StandaloneWindows; } private static bool sf_CanDeploy() { BuildTarget target = s_target; return target == BuildTarget.StandaloneWindows64 || target == BuildTarget.StandaloneWindows || target == BuildTarget.iOS || target == BuildTarget.Android; } public static bool IsSupportPlatform(BuildTarget target) { return target == BuildTarget.StandaloneWindows64 || target == BuildTarget.StandaloneWindows || target == BuildTarget.iOS || target == BuildTarget.Android; } public static string SelectBuildPath(BuildTarget target, string folder) { if (target == BuildTarget.iOS) { return EditorUtility.SaveFolderPanel("Select Build Path...", folder, ""); } else { string ext_name; switch (target) { case BuildTarget.Android: ext_name = "apk"; break; default: case BuildTarget.StandaloneWindows64: case BuildTarget.StandaloneWindows: ext_name = "exe"; break; } return EditorUtility.SaveFilePanel("Select Build Path...", folder, "", ext_name); } } private static void sf_CreateOneClickBuildBatchAfterDeploy(string build_path) { string batch_path = "build_" + System.IO.Path.GetFileNameWithoutExtension(build_path) + ".bat"; sf_CreateOneClickBuildBatch(batch_path, s_target, build_path); s_previous_build_batch_filename = batch_path; } public static void CreateOneClickBuildBatch(string batch_path, BuildBatchInfo info) { string batch_filename_without_ext = System.IO.Path.GetFileNameWithoutExtension(batch_path); string json = UnityEngine.JsonUtility.ToJson(info, true); string json_filename = batch_filename_without_ext + "_info.json"; System.IO.File.WriteAllText(json_filename, json); string[] batch_content = { "@ECHO OFF", "REM Setup custom script (option)", "REM SET post_build_script=PostBuildScript.Execute\n", "SETLOCAL enableextensions enabledelayedexpansion", "SET batch_path=%~dp0", "REM Setup this batch path to project path", "SET project_path=%batch_path%", "REM remove the last '\\' chararctor =======================", "IF \"%project_path:~-1%\" == \"\\\" (", " SET project_path=%project_path:~0,-1%", ")", "REM ======================================================\n", "REM Setup Unity Root Path", "SET unity_x86_path=C:\\Program Files (x86)\\Unity", "SET unity_x64_path=C:\\Program Files\\Unity\n", "IF EXIST \"%unity_x64_path%\" (", " SET unity_exe=\"%unity_x64_path%\\Editor\\Unity.exe\"", ") ElSE (", " SET unity_exe=\"%unity_x86_path%\\Editor\\Unity.exe\"", ")\n", "REM Check out if the unity exe is exist...", "IF Not EXIST %unity_exe% (", " ECHO [Batch Error] Please check the settings of the unity.exe", " ECHO [Batch Error] %unity_exe% is not exist", " PAUSE", " EXIT", ")\n", "SET build_log_path=%USERPROFILE%\\AppData\\Local\\Unity\\Editor\n", "REM Start to build...", "CALL %unity_exe% -quit -batchmode -serial %serial% -username \"%username%\" -password \"%password%\" -projectPath \"%project_path%\" -executeMethod ucDeploy.Execute2 --build-info-json \"" + json_filename + "\"\n", "REM when the error occur, open the folder of the build log.", "IF %ERRORLEVEL% NEQ 0 (", " ECHO Build Failed...Orz", " %SystemRoot%\\explorer.exe %build_log_path%", ") ELSE (", " ECHO Build Success...XDDDD", ")\n", "PAUSE" }; System.IO.File.WriteAllLines(batch_path, batch_content); } private static void sf_CreateOneClickBuildBatch(string batch_path, BuildTarget target, string build_path) { BuildBatchInfo info = CreateBuildBatchInfo(target, build_path); CreateOneClickBuildBatch(batch_path, info); } private static string s_str_hash_code { get { return UnityEngine.Animator.StringToHash(UnityEngine.Application.dataPath).ToString(); } } private static string s_previous_build_path { get { return EditorPrefs.GetString("ucDeployToolPreviousPath_" + s_str_hash_code); } set { EditorPrefs.SetString("ucDeployToolPreviousPath_" + s_str_hash_code, value); } } private static string s_previous_build_batch_filename { get { return EditorPrefs.GetString("ucDeployToolPreviousBatch_" + s_str_hash_code); } set { EditorPrefs.SetString("ucDeployToolPreviousBatch_" + s_str_hash_code, value); } } private static bool s_can_quick_deploy { get { return EditorPrefs.GetBool("ucDeployToolCanQuickDeploy_" + s_str_hash_code); } set { EditorPrefs.SetBool("ucDeployToolCanQuickDeploy_" + s_str_hash_code, value); } } private static bool s_auto_create_one_click_build_batch_when_deploy { get { return EditorPrefs.GetBool("ucDeployToolACOCBBWD_" + s_str_hash_code); } set { EditorPrefs.SetBool("ucDeployToolACOCBBWD_" + s_str_hash_code, value); } } private static BuildTarget s_target { get { return (BuildTarget)EditorPrefs.GetInt("ucDeployToolTarget_" + s_str_hash_code); } set { EditorPrefs.SetInt("ucDeployToolTarget_" + s_str_hash_code, (int)value); } } } #if false public sealed class OneClickBuildBatchCreateQuicklyWizard : ScriptableWizard { public string Platform; public string BuildPath; public string Filename; public string[] scenes; public bool OpenBuildPath; [MenuItem("ucDeploy/One Click Build Batch/Show Quick Info _F8", true)] static bool CanCreateWindow() { return ucDeployTool.CanOneClickBuildBatchh_CreateQuickly(); } [MenuItem("ucDeploy/One Click Build Batch/Show Quick Info _F8", false, 800)] static void CreateWindow() { ScriptableWizard.DisplayWizard("Show Quick Info.", typeof(OneClickBuildBatchCreateQuicklyWizard), "Close"); } void OnWizardUpdate() { BuildBatchInfo info = ucDeployTool.CreateBuildBatchInfo(ucDeployTool.GetTarget(), ucDeployTool.GetBuildPath()); Platform = info.platform; BuildPath = info.build_path; Filename = info.filename; scenes = info.scenes; OpenBuildPath = info.neeed_open_the_folder_when_sccuess; } } #endif