├── AutoBuild.cs ├── README.md └── version.ini /AutoBuild.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System; 4 | using System.Collections; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.IO; 9 | using System.IO.Compression; 10 | // this uses the Unity port of DotNetZip https://github.com/r2d2rigo/dotnetzip-for-unity 11 | using Ionic.Zip; 12 | 13 | // place in an "Editor" folder in your Assets folder 14 | public class AutoBuild 15 | { 16 | // TODO: turn this into a wizard or something??? whatever 17 | 18 | /// 19 | /// 时间戳格式 用于版本号及压缩包 20 | /// 21 | public static string TIME_FORMAT = "yyyyMMdd"; 22 | // public static string TIME_FORMAT = "yyyyMMdd HH:mm:ss"; 23 | // public static string ZIP_TIME_FORMAT = "yyyyMMdd HH_mm_ss"; 24 | private static string bundleVersion; 25 | 26 | 27 | //MSDN: https://docs.microsoft.com/en-us/dotnet/api/system.io.compression.ziparchive?redirectedfrom=MSDN&view=netframework-4.7.2 28 | // static void Main(string[] args) 29 | // { 30 | // using (FileStream zipToOpen = new FileStream(@"c:\users\exampleuser\release.zip", FileMode.Open)) 31 | // { 32 | // using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update)) 33 | // { 34 | // ZipArchiveEntry readmeEntry = archive.CreateEntry("Readme.txt"); 35 | // using (StreamWriter writer = new StreamWriter(readmeEntry.Open())) 36 | // { 37 | // writer.WriteLine("Information about this package."); 38 | // writer.WriteLine("========================"); 39 | // } 40 | // } 41 | // } 42 | // } 43 | 44 | [MenuItem("打包/Build Windows64")] 45 | public static void StartWindows() 46 | { 47 | // Get filename. 48 | // string path = EditorUtility.SaveFolderPanel("Build out WINDOWS to...", 49 | // GetProjectFolderPath() + "/Builds/", 50 | // ""); 51 | // var filename = path.Split('/'); // do this so I can grab the project folder name 52 | // var buildPath = "D:\\Unity\\Projects\\Builds"; 53 | var buildPath = GetProjectFolderPath() + "/Builds/"; 54 | 55 | var name = BuildConfig.SchoolName; 56 | 57 | var appDir = buildPath + name; 58 | 59 | Debug.Log("Start building at "+appDir); 60 | 61 | 62 | PreBuild(buildPath, appDir); 63 | BuildPlayer ( BuildTarget.StandaloneWindows64, name, buildPath );//BuildTarget.StandaloneWindows 64 | } 65 | 66 | static void DeleteAll(string path) 67 | { 68 | if (!Directory.Exists(path)) 69 | { 70 | return; 71 | } 72 | 73 | //删除所有文件 74 | foreach (var file in Directory.GetFiles(path)) 75 | { 76 | // //保留版本信息 77 | // if (file.Contains("version.ini")) 78 | // { 79 | // continue; 80 | // } 81 | 82 | File.Delete(file); 83 | } 84 | 85 | //递归删除所有文件夹 86 | foreach (var subDir in Directory.GetDirectories(path)) 87 | { 88 | // //保留msc文件夹 89 | // if (subDir.Contains("msc")) 90 | // { 91 | // continue; 92 | // } 93 | 94 | DeleteAll(subDir); 95 | Directory.Delete(subDir); 96 | } 97 | } 98 | 99 | /// 100 | /// 删除之前的内容 101 | /// 102 | /// 103 | private static void PreBuild(string buildDir, string appDir) 104 | { 105 | if (!Directory.Exists(buildDir)) 106 | { 107 | Directory.CreateDirectory(buildDir); 108 | } 109 | if (!Directory.Exists(appDir)) 110 | { 111 | Directory.CreateDirectory(appDir); 112 | } 113 | 114 | // Debug.Log("【AutoBuild】"+buildDir); 115 | // Debug.Log("【AutoBuild】"+appDir); 116 | 117 | DeleteAll(appDir); 118 | 119 | // WriteVersion(appDir); 120 | IncreaseVersion(); 121 | 122 | CopyMsc(appDir); 123 | } 124 | 125 | private static void IncreaseVersion() 126 | { 127 | var oldVersion = PlayerSettings.bundleVersion; 128 | Debug.Log("【AutoBuild】当前版本:"+oldVersion); 129 | float oldVersionCode = float.Parse(oldVersion.Split('_')[0].Replace("v","")); 130 | float newVersionCode = oldVersionCode + 0.1f; 131 | bundleVersion = string.Format("v{0}_{1}", newVersionCode, DateTime.Now.ToString(TIME_FORMAT)); 132 | PlayerSettings.bundleVersion = bundleVersion; 133 | Debug.Log("【AutoBuild】最新版本:"+bundleVersion); 134 | } 135 | 136 | /// 137 | /// 拷贝msc资源文件 讯飞语音 138 | /// 139 | /// 140 | private static void CopyMsc(string appDir) 141 | { 142 | string sourceDirectory = GetProjectFolderPath()+"/msc"; 143 | string targetDirectory = appDir+"/msc"; 144 | 145 | DirectoryInfo diSource = new DirectoryInfo(sourceDirectory); 146 | DirectoryInfo diTarget = new DirectoryInfo(targetDirectory); 147 | 148 | CopyAll(diSource, diTarget); 149 | } 150 | 151 | public static void CopyAll(DirectoryInfo source, DirectoryInfo target) 152 | { 153 | if (source.FullName.ToLower() == target.FullName.ToLower()) 154 | { 155 | return; 156 | } 157 | 158 | // Check if the target directory exists, if not, create it. 159 | if (Directory.Exists(target.FullName) == false) 160 | { 161 | Directory.CreateDirectory(target.FullName); 162 | } 163 | 164 | // Copy each file into it's new directory. 165 | foreach (FileInfo fi in source.GetFiles()) 166 | { 167 | // Debug.Log(string.Format(@"Copying {0}\{1}", target.FullName, fi.Name)); 168 | fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true); 169 | } 170 | 171 | // Copy each subdirectory using recursion. 172 | foreach (DirectoryInfo diSourceSubDir in source.GetDirectories()) 173 | { 174 | DirectoryInfo nextTargetSubDir = 175 | target.CreateSubdirectory(diSourceSubDir.Name); 176 | CopyAll(diSourceSubDir, nextTargetSubDir); 177 | } 178 | } 179 | 180 | /// 181 | /// 自动写入版本信息 182 | /// 183 | /// 184 | private static void WriteVersion(string dstPath) 185 | { 186 | dstPath += "/version.ini"; 187 | var srcPath = Application.dataPath + "/Plugins/version.ini"; 188 | // Debug.Log("【BuildRadiator】" + srcPath); 189 | // Debug.Log("【BuildRadiator】" + dstPath); 190 | // Debug.Log("【AutoBuild】" + File.Exists(srcPath) + "," + File.Exists(dstPath)); 191 | 192 | 193 | //1.读旧版本信息 194 | string oldVersion; 195 | using (StreamReader sr = new StreamReader(srcPath)) 196 | { 197 | oldVersion = sr.ReadToEnd(); 198 | } 199 | 200 | //2.更新版本号,写时间戳 201 | string newVersion; 202 | using (StreamWriter sw = new StreamWriter(srcPath, false)) 203 | { 204 | int oldVersionCode = int.Parse(oldVersion.Split(',')[0]); 205 | var newVersionCode = oldVersionCode + 1; 206 | newVersion = 207 | newVersionCode + ", BuildTime: " + DateTime.Now.ToString(TIME_FORMAT); 208 | sw.WriteLine(newVersion); 209 | } 210 | 211 | //3.同步到打包路径 212 | // if (!File.Exists(dstPath)) 213 | // { 214 | // File.CreateText(dstPath); 215 | // } 216 | using (StreamWriter sw = new StreamWriter(dstPath, false)) 217 | { 218 | sw.WriteLine(newVersion); 219 | } 220 | } 221 | 222 | 223 | // [MenuItem("BuildRadiator/Build Windows + Mac OSX + Linux")] 224 | public static void StartAll() 225 | { 226 | // Get filename. 227 | string path = EditorUtility.SaveFolderPanel("Build out ALL STANDALONES to...", 228 | GetProjectFolderPath() + "/Builds/", 229 | ""); 230 | var filename = path.Split('/'); // do this so I can grab the project folder name 231 | // BuildPlayer ( BuildTarget.StandaloneOSXUniversal, filename[filename.Length-1], path + "/" ); 232 | BuildPlayer(BuildTarget.StandaloneLinuxUniversal, filename[filename.Length - 1], 233 | path + "/"); 234 | BuildPlayer(BuildTarget.StandaloneWindows64, filename[filename.Length - 1], path + "/"); 235 | } 236 | 237 | // this is the main player builder function 238 | static void BuildPlayer(BuildTarget buildTarget, string filename, string path) 239 | { 240 | string fileExtension = ""; 241 | string dataPath = ""; 242 | string modifier = ""; 243 | 244 | // configure path variables based on the platform we're targeting 245 | switch (buildTarget) 246 | { 247 | case BuildTarget.StandaloneWindows: 248 | case BuildTarget.StandaloneWindows64: 249 | // modifier = "_windows"; 250 | fileExtension = ".exe"; 251 | dataPath = "_Data/"; 252 | break; 253 | case BuildTarget.StandaloneOSXIntel: 254 | case BuildTarget.StandaloneOSXIntel64: 255 | // case BuildTarget.StandaloneOSXUniversal: 256 | // modifier = "_mac-osx"; 257 | // fileExtension = ".app"; 258 | // dataPath = fileExtension + "/Contents/"; 259 | // break; 260 | case BuildTarget.StandaloneLinux: 261 | case BuildTarget.StandaloneLinux64: 262 | case BuildTarget.StandaloneLinuxUniversal: 263 | modifier = "_linux"; 264 | dataPath = "_Data/"; 265 | switch (buildTarget) 266 | { 267 | case BuildTarget.StandaloneLinux: 268 | fileExtension = ".x86"; 269 | break; 270 | case BuildTarget.StandaloneLinux64: 271 | fileExtension = ".x64"; 272 | break; 273 | case BuildTarget.StandaloneLinuxUniversal: 274 | fileExtension = ".x86_64"; 275 | break; 276 | } 277 | 278 | break; 279 | } 280 | 281 | // Debug.Log("====== BuildPlayer: " + buildTarget.ToString() + " at " + path + filename); 282 | EditorUserBuildSettings.SwitchActiveBuildTarget(buildTarget); 283 | 284 | // build out the player 285 | string buildPath = path + filename + modifier + "/"; 286 | // Debug.Log("buildpath: " + buildPath); 287 | string playerPath = buildPath + filename + modifier + fileExtension; 288 | // Debug.Log("playerpath: " + playerPath); 289 | BuildPipeline.BuildPlayer(GetScenePaths(), playerPath, buildTarget, 290 | buildTarget == BuildTarget.StandaloneWindows64 291 | ? BuildOptions.ShowBuiltPlayer 292 | : BuildOptions.None); 293 | 294 | // Copy files over into builds 295 | string fullDataPath = buildPath + filename + modifier + dataPath; 296 | // Debug.Log("fullDataPath: " + fullDataPath); 297 | // CopyFromProjectAssets( fullDataPath, "languages"); // language text files that Radiator uses 298 | // copy over readme 299 | 300 | // string zipTime = DateTime.Now.ToString(ZIP_TIME_FORMAT); 301 | // ZIP everything 302 | // var zipPath = path + "HahaRobotCoach.zip"; 303 | var zipPath = path + BuildConfig.SchoolName + modifier + "_" + bundleVersion + ".zip"; 304 | Debug.Log("Build finished at "+buildPath); 305 | CompressDirectory(buildPath, zipPath); 306 | } 307 | 308 | // from http://wiki.unity3d.com/index.php?title=AutoBuilder 309 | static string[] GetScenePaths() 310 | { 311 | string[] scenes = new string[EditorBuildSettings.scenes.Length]; 312 | for (int i = 0; i < scenes.Length; i++) 313 | { 314 | scenes[i] = EditorBuildSettings.scenes[i].path; 315 | } 316 | 317 | return scenes; 318 | } 319 | 320 | static string GetProjectName() 321 | { 322 | string[] s = Application.dataPath.Split('/'); 323 | return s[s.Length - 2]; 324 | } 325 | 326 | static string GetProjectFolderPath() 327 | { 328 | var s = Application.dataPath; 329 | s = s.Substring(0,s.Length - 7); // remove "Assets/" 330 | return s; 331 | } 332 | 333 | // copies over files from somewhere in my project folder to my standalone build's path 334 | // do not put a "/" at beginning of assetsFolderName 335 | static void CopyFromProjectAssets(string fullDataPath, string assetsFolderPath, 336 | bool deleteMetaFiles = true) 337 | { 338 | // Debug.Log("CopyFromProjectAssets: copying over " + assetsFolderPath); 339 | FileUtil.ReplaceDirectory(Application.dataPath + "/" + assetsFolderPath, 340 | fullDataPath + assetsFolderPath); // copy over languages 341 | 342 | // delete all meta files 343 | if (deleteMetaFiles) 344 | { 345 | var metaFiles = Directory.GetFiles(fullDataPath + assetsFolderPath, "*.meta", 346 | SearchOption.AllDirectories); 347 | foreach (var meta in metaFiles) 348 | { 349 | FileUtil.DeleteFileOrDirectory(meta); 350 | } 351 | } 352 | } 353 | 354 | // compress the folder into a ZIP file, uses https://github.com/r2d2rigo/dotnetzip-for-unity 355 | static void CompressDirectory(string directory, string zipFileOutputPath) 356 | { 357 | // Debug.Log("Attempting to compress " + directory + " into " + zipFileOutputPath); 358 | // display fake percentage, I can't get zip.SaveProgress event handler to work for some reason, whatever 359 | EditorUtility.DisplayProgressBar("COMPRESSING... please wait", zipFileOutputPath, 0.38f); 360 | using (ZipFile zip = new ZipFile()) 361 | { 362 | zip.ParallelDeflateThreshold = 363 | -1; // DotNetZip bugfix that corrupts DLLs / binaries http://stackoverflow.com/questions/15337186/dotnetzip-badreadexception-on-extract 364 | zip.AddDirectory(directory); 365 | zip.Save(zipFileOutputPath); 366 | } 367 | 368 | EditorUtility.ClearProgressBar(); 369 | 370 | Debug.Log("Compress finished at " + zipFileOutputPath); 371 | 372 | } 373 | } 374 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UnityAutoBuild 2 | UnityAutoBuild = Build + Zip + Version Control 3 | -------------------------------------------------------------------------------- /version.ini: -------------------------------------------------------------------------------- 1 | 24, BuildTime: 20190125 11:45:10 2 | --------------------------------------------------------------------------------