├── CHANGELOG.md ├── CHANGELOG.md.meta ├── Editor.meta ├── Editor ├── BuildManager.Editor.asmdef ├── BuildManager.Editor.asmdef.meta ├── BuildManager.meta ├── BuildManager │ ├── BuildPipeline.meta │ ├── BuildPipeline │ │ ├── BuildData.cs │ │ ├── BuildData.cs.meta │ │ ├── BuildManager.cs │ │ ├── BuildManager.cs.meta │ │ ├── BuildManagerSettings.cs │ │ ├── BuildManagerSettings.cs.meta │ │ ├── BuildSequence.cs │ │ └── BuildSequence.cs.meta │ ├── DefaultBuildSequences.asset │ ├── DefaultBuildSequences.asset.meta │ ├── DotNetZip.dll │ └── DotNetZip.dll.meta ├── Changelog.meta ├── Changelog │ ├── ChangelogData.cs │ └── ChangelogData.cs.meta ├── Window.meta └── Window │ ├── BuildDataReordableList.cs │ ├── BuildDataReordableList.cs.meta │ ├── BuildManagerWindow.cs │ ├── BuildManagerWindow.cs.meta │ ├── BuildSequenceReordableList.cs │ ├── BuildSequenceReordableList.cs.meta │ ├── PredefinedBuildConfigs.cs │ └── PredefinedBuildConfigs.cs.meta ├── HelpScreenshots.meta ├── HelpScreenshots ├── 1.png ├── 1.png.meta ├── 2.png ├── 2.png.meta ├── 3.png ├── 3.png.meta ├── 4.png ├── 4.png.meta ├── 5.png ├── 5.png.meta ├── 6.png ├── 6.png.meta ├── 7.png ├── 7.png.meta ├── 8.png ├── 8.png.meta ├── 9.png └── 9.png.meta ├── LICENSE ├── LICENSE.meta ├── README.md ├── README.md.meta ├── package.json └── package.json.meta /CHANGELOG.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-on/UnityBuildManager/5ccccffd24b63fdfe65d45a02362e5798e941ee1/CHANGELOG.md -------------------------------------------------------------------------------- /CHANGELOG.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0b782977bc2b4e2e8ffbd84faadd9499 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c08f997806394ca4ac286dc0a63a272f 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/BuildManager.Editor.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BuildManager.Editor", 3 | "references": [ 4 | "GUID:432b8b1a65d435f458d6969ef99d85e2", 5 | "GUID:46cc2325ddc967847a6e9ca3f6ebd47f", 6 | "GUID:900335979416f53469b06aabef8b32d8" 7 | ], 8 | "includePlatforms": [ 9 | "Editor" 10 | ], 11 | "excludePlatforms": [], 12 | "allowUnsafeCode": false, 13 | "overrideReferences": false, 14 | "precompiledReferences": [], 15 | "autoReferenced": true, 16 | "defineConstraints": [], 17 | "versionDefines": [], 18 | "noEngineReferences": false 19 | } -------------------------------------------------------------------------------- /Editor/BuildManager.Editor.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 152317f22371ca549818b9b6093f9a4e 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Editor/BuildManager.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d2a7ca94659cedb469255cdd2e72755c 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/BuildManager/BuildPipeline.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 77f57a9cd5baa8f419d189c167cb62af 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/BuildManager/BuildPipeline/BuildData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | 6 | [Serializable] 7 | public class BuildData : ICloneable { 8 | public bool isEnabled = false; 9 | 10 | public string outputRoot; 11 | public string middlePath; 12 | public string dirPathForPostProcess; 13 | 14 | public bool isPassbyBuild = false; //Use it to simulate build and give to after build hooks previously build game 15 | 16 | public string scriptingDefineSymbolsOverride; 17 | 18 | public BuildTargetGroup targetGroup; 19 | public BuildTarget target; 20 | public BuildOptions options; 21 | 22 | public bool isVirtualRealitySupported; 23 | 24 | public bool isReleaseBuild; // Maximum compressed build with Release IL2CPP 25 | 26 | public bool needZip; 27 | 28 | public bool needItchPush; 29 | public string itchChannel; 30 | 31 | public bool needGithubPush; 32 | 33 | //TODO: 34 | public bool needGamejolthPush; 35 | public bool needSteamPush; 36 | public bool needGoogleDrivePush; 37 | 38 | public BuildData() : this( 39 | BuildTargetGroup.Unknown, 40 | BuildTarget.NoTarget 41 | ) { 42 | 43 | } 44 | 45 | public BuildData(BuildTargetGroup targetGroup, BuildTarget target) { 46 | this.targetGroup = targetGroup; 47 | this.target = target; 48 | 49 | isEnabled = true; 50 | isPassbyBuild = false; 51 | 52 | scriptingDefineSymbolsOverride = ""; 53 | 54 | options = BuildOptions.None; 55 | isVirtualRealitySupported = false; 56 | 57 | outputRoot = "Builds/"; 58 | middlePath = "$NAME_$VERSION_$PLATFORM/$NAME_$VERSION/$NAME$EXECUTABLE"; 59 | dirPathForPostProcess = "$NAME_$VERSION_$PLATFORM"; 60 | 61 | isReleaseBuild = false; 62 | 63 | needZip = false; 64 | dirPathForPostProcess = "$NAME_$VERSION_$PLATFORM"; 65 | 66 | needItchPush = false; 67 | itchChannel = "channel"; 68 | 69 | needGithubPush = false; 70 | 71 | //TODO: 72 | needGamejolthPush = false; 73 | needSteamPush = false; 74 | needGoogleDrivePush = false; 75 | } 76 | 77 | public object Clone() { 78 | return this.MemberwiseClone(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Editor/BuildManager/BuildPipeline/BuildData.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f881ca5fbb3018a4a8d6f782f616cb7b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/BuildManager/BuildPipeline/BuildManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Linq; 4 | using System.Text; 5 | using System.IO; 6 | using System.Diagnostics; 7 | using UnityEngine; 8 | using UnityEditor; 9 | using UnityEditor.Build.Reporting; 10 | using Ionic.Zip; 11 | 12 | using Debug = UnityEngine.Debug; 13 | 14 | public static class BuildManager { 15 | const string butlerDownloadPath = "https://broth.itch.ovh/butler/windows-386/LATEST/archive/default"; 16 | const string githubReleasesDownloadPath = "https://github.com/github-release/github-release/releases/download/v0.9.0/windows-amd64-github-release.zip"; 17 | 18 | const string butlerRelativePath = @"Editor/Butler/butler.exe"; 19 | const string githubReleasesRelativePath = @"Editor/Github/github-release.exe"; 20 | 21 | static DateTime usedDate; 22 | 23 | static string buildNameString; 24 | 25 | static string[] buildsPath; 26 | 27 | static ChangelogData usedChangelog; 28 | 29 | public static void RunBuildSequnce(BuildManagerSettings settings, BuildSequence sequence, ChangelogData changelog) { 30 | // Start init 31 | usedChangelog = changelog; 32 | ChangelogData.ChangelogVersionEntry usedChangelogEntry = changelog.GetLastVersion(); 33 | buildNameString = usedChangelogEntry.GetVersionHeader(); 34 | 35 | #if GAME_TEMPLATE 36 | TemplateGameManager.Instance.buildNameString = buildNameString; 37 | TemplateGameManager.Instance.productName = PlayerSettings.productName; 38 | EditorUtility.SetDirty(TemplateGameManager.Instance); 39 | #endif 40 | usedDate = DateTime.Now; 41 | //End init 42 | 43 | Debug.Log("Start building all"); 44 | DateTime startTime = DateTime.Now; 45 | 46 | //Crete release here, because build's not get pushed 47 | CreateGitHubReleaseIfNeeded(settings, sequence); 48 | 49 | Build(settings, sequence); 50 | PostBuild(sequence); 51 | 52 | Compress(sequence); 53 | 54 | ItchioPush(settings, sequence, changelog); 55 | GithubPush(settings, sequence, changelog); 56 | 57 | Debug.Log($"End building all. Elapsed time: {string.Format("{0:mm\\:ss}", DateTime.Now - startTime)}"); 58 | 59 | #if UNITY_EDITOR_WIN 60 | ShowExplorer(sequence.builds[sequence.builds.Count - 1].outputRoot); 61 | #endif 62 | } 63 | 64 | static void Build(BuildManagerSettings settings, BuildSequence sequence) { 65 | BuildTarget targetBeforeStart = EditorUserBuildSettings.activeBuildTarget; 66 | BuildTargetGroup targetGroupBeforeStart = BuildPipeline.GetBuildTargetGroup(targetBeforeStart); 67 | string definesBeforeStart = PlayerSettings.GetScriptingDefineSymbolsForGroup(targetGroupBeforeStart); 68 | bool isVRSupported = PlayerSettings.virtualRealitySupported; //TODO: PlayerSettings.virtualRealitySupported is deprecated. Replace with smth new 69 | 70 | buildsPath = new string[sequence.builds.Count]; 71 | for (byte i = 0; i < sequence.builds.Count; ++i) { 72 | BuildData data = sequence.builds[i]; 73 | 74 | if (!data.isEnabled) 75 | continue; 76 | 77 | if (PlayerSettings.virtualRealitySupported != data.isVirtualRealitySupported) 78 | PlayerSettings.virtualRealitySupported = data.isVirtualRealitySupported; 79 | 80 | buildsPath[i] = BaseBuild( 81 | data.targetGroup, 82 | data.target, 83 | data.options, 84 | data.outputRoot + GetPathWithVars(data, data.middlePath), 85 | string.Concat(settings.scriptingDefineSymbols, ";", sequence.scriptingDefineSymbolsOverride, ";", data.scriptingDefineSymbolsOverride), 86 | data.isPassbyBuild, 87 | data.isReleaseBuild 88 | ); 89 | 90 | 91 | } 92 | 93 | EditorUserBuildSettings.SwitchActiveBuildTarget(targetGroupBeforeStart, targetBeforeStart); 94 | PlayerSettings.SetScriptingDefineSymbolsForGroup(targetGroupBeforeStart, definesBeforeStart); 95 | PlayerSettings.virtualRealitySupported = isVRSupported; 96 | } 97 | 98 | static void PostBuild(BuildSequence sequence) { 99 | bool isNeedChangelogFile = usedChangelog.versions.Count != 0; 100 | bool isNeedReadmeFile = !string.IsNullOrEmpty(usedChangelog.readme); 101 | string changelogContent = ""; 102 | string readmeContent = usedChangelog.readme; 103 | 104 | bool isAnyReleaseBuild = false; 105 | 106 | if (isNeedChangelogFile) { 107 | changelogContent = usedChangelog.GetChangelogString(); 108 | } 109 | 110 | for (byte i = 0; i < sequence.builds.Count; ++i) { 111 | if (!sequence.builds[i].isEnabled) 112 | continue; 113 | 114 | if (!string.IsNullOrEmpty(buildsPath[i])) { 115 | if (sequence.builds[i].isReleaseBuild) { //Destroy IL2CPP junk after build 116 | isAnyReleaseBuild = true; 117 | 118 | string buildRootPath = Path.GetDirectoryName(buildsPath[i]); 119 | string[] dirs = Directory.GetDirectories(buildRootPath); 120 | var il2cppDirs = dirs.Where(s => s.Contains("BackUpThisFolder_ButDontShipItWithYourGame")); 121 | foreach (var dir in il2cppDirs) 122 | Directory.Delete(dir, true); 123 | } 124 | 125 | #if UNITY_EDITOR_WIN 126 | //https://forum.unity.com/threads/mac-unity-build-from-a-pc-not-opening-on-mac.947727/ 127 | //Use git bash to execute this command 128 | if (sequence.builds[i].target == BuildTarget.StandaloneOSX) { 129 | Debug.Log($"chmod -R 777 {sequence.builds[i].outputRoot + GetPathWithVars(sequence.builds[i], sequence.builds[i].middlePath)}.app"); 130 | 131 | Process process = new Process() { 132 | StartInfo = new ProcessStartInfo { 133 | WindowStyle = ProcessWindowStyle.Hidden, 134 | FileName = "cmd.exe", 135 | Arguments = $"start \"\" \" %PROGRAMFILES%\\Git\\bin\\sh.exe\" --chmod -R 777 {sequence.builds[i].outputRoot + GetPathWithVars(sequence.builds[i], sequence.builds[i].middlePath)}.app", 136 | }, 137 | }; 138 | process.Start(); 139 | } 140 | #endif 141 | 142 | if(sequence.builds[i].targetGroup == BuildTargetGroup.Standalone) { 143 | string path = Path.Combine(sequence.builds[i].outputRoot + GetPathWithVars(sequence.builds[i], sequence.builds[i].middlePath)).Replace(@"/", @"\"); 144 | path = path.Substring(0, path.LastIndexOf("\\")); 145 | 146 | if (isNeedChangelogFile) { 147 | File.WriteAllText( 148 | Path.Combine(path, "Changelog.txt"), 149 | changelogContent 150 | ); 151 | } 152 | 153 | if (isNeedReadmeFile) { 154 | File.WriteAllText( 155 | Path.Combine(path, "Readme.txt"), 156 | readmeContent 157 | ); 158 | } 159 | } 160 | } 161 | } 162 | 163 | if (isAnyReleaseBuild) { 164 | string gitRootPath = Path.Combine(Application.dataPath, ".."); 165 | 166 | if(!Directory.Exists(Path.Combine(gitRootPath, ".git"))) { 167 | gitRootPath = Path.Combine(gitRootPath, ".."); 168 | 169 | if (!Directory.Exists(Path.Combine(gitRootPath, ".git"))) { 170 | gitRootPath = null; 171 | } 172 | } 173 | 174 | if(gitRootPath != null) { 175 | if (isNeedChangelogFile) { 176 | File.WriteAllText( 177 | Path.Combine(gitRootPath, "Changelog.md"), 178 | changelogContent 179 | ); 180 | } 181 | 182 | if (isNeedReadmeFile) { 183 | File.WriteAllText( 184 | Path.Combine(gitRootPath, "ReadmeGame.md"), 185 | readmeContent 186 | ); 187 | } 188 | } 189 | } 190 | } 191 | 192 | static void Compress(BuildSequence sequence) { 193 | for (byte i = 0; i < sequence.builds.Count; ++i) { 194 | if (!sequence.builds[i].needZip || !sequence.builds[i].isEnabled) 195 | continue; 196 | 197 | if (sequence.builds[i].target == BuildTarget.Android) { 198 | Debug.Log("Skip android build to .zip, because .apk files already compressed"); 199 | continue; 200 | } 201 | 202 | if (!string.IsNullOrEmpty(buildsPath[i])) 203 | BaseCompress(sequence.builds[i].outputRoot + GetPathWithVars(sequence.builds[i], sequence.builds[i].dirPathForPostProcess)); 204 | else 205 | Debug.LogWarning($"[Compressing] Can't find build for {GetBuildTargetExecutable(sequence.builds[i].target)}"); 206 | } 207 | } 208 | 209 | static void ItchioPush(BuildManagerSettings settings, BuildSequence sequence, ChangelogData changelog) { 210 | for (byte i = 0; i < sequence.builds.Count; ++i) { 211 | if (!sequence.builds[i].isEnabled || !sequence.builds[i].needItchPush) 212 | continue; 213 | 214 | if (!string.IsNullOrEmpty(buildsPath[i])) { 215 | if (string.IsNullOrEmpty(settings.itchGameLink)) { 216 | Debug.LogWarning($"Can't push itch.io. Required data is missing"); 217 | return; 218 | } 219 | 220 | PushItch(settings, sequence, sequence.builds[i]); 221 | } 222 | else { 223 | Debug.LogWarning($"[Itch.io push] Can't find build for {GetBuildTargetExecutable(sequence.builds[i].target)}"); 224 | } 225 | } 226 | } 227 | 228 | static void GithubPush(BuildManagerSettings settings, BuildSequence sequence, ChangelogData changelog) { 229 | for (byte i = 0; i < sequence.builds.Count; ++i) { 230 | if (!sequence.builds[i].isEnabled || !sequence.builds[i].needGithubPush) 231 | continue; 232 | 233 | if (!string.IsNullOrEmpty(buildsPath[i])) { 234 | if (string.IsNullOrEmpty(settings.GithubToken) || string.IsNullOrEmpty(settings.githubUserName) || string.IsNullOrEmpty(settings.githubRepoName)) { 235 | Debug.LogWarning($"Can't push github release. Required data is missing"); 236 | return; 237 | } 238 | 239 | PushGithub(settings, sequence, sequence.builds[i]); 240 | } 241 | else { 242 | Debug.LogWarning($"[GitHub push] Can't find build for {GetBuildTargetExecutable(sequence.builds[i].target)}"); 243 | } 244 | } 245 | } 246 | 247 | #region Convert to strings 248 | public static string GetPathWithVars(BuildData data, string s) { 249 | s = s.Replace("$NAME", GetProductName()); 250 | s = s.Replace("$PLATFORM", ConvertBuildTargetToString(data.target)); 251 | s = s.Replace("$VERSION", PlayerSettings.bundleVersion); 252 | s = s.Replace("$DATESHORT", $"{usedDate.Date.Year % 100}_{usedDate.Date.Month}_{usedDate.Date.Day}"); 253 | s = s.Replace("$YEARSHORT", $"{usedDate.Date.Year % 100}"); 254 | s = s.Replace("$DATE", $"{usedDate.Date.Year}_{usedDate.Date.Month}_{usedDate.Date.Day}"); 255 | s = s.Replace("$YEAR", $"{usedDate.Date.Year}"); 256 | s = s.Replace("$MONTH", $"{usedDate.Date.Month}"); 257 | s = s.Replace("$DAY", $"{usedDate.Date.Day}"); 258 | s = s.Replace("$TIME", $"{usedDate.Hour}_{usedDate.Minute}"); 259 | s = s.Replace("$EXECUTABLE", GetBuildTargetExecutable(data.target)); 260 | return s; 261 | } 262 | 263 | public static string GetPathWithVarsForZip(BuildData data, string s) { 264 | s = s.Replace("$NAME", GetProductName()); 265 | s = s.Replace("$PLATFORM", ConvertBuildTargetToString(data.target)); 266 | s = s.Replace("$VERSION", PlayerSettings.bundleVersion); 267 | s = s.Replace("$DATESHORT", $"{usedDate.Date.Year % 100}_{usedDate.Date.Month}_{usedDate.Date.Day}"); 268 | s = s.Replace("$YEARSHORT", $"{usedDate.Date.Year % 100}"); 269 | s = s.Replace("$DATE", $"{usedDate.Date.Year}_{usedDate.Date.Month}_{usedDate.Date.Day}"); 270 | s = s.Replace("$YEAR", $"{usedDate.Date.Year}"); 271 | s = s.Replace("$MONTH", $"{usedDate.Date.Month}"); 272 | s = s.Replace("$DAY", $"{usedDate.Date.Day}"); 273 | s = s.Replace("$TIME", $"{usedDate.Hour}_{usedDate.Minute}"); 274 | 275 | if (s.Contains("$EXECUTABLE")) 276 | s = s.Replace("$EXECUTABLE", GetBuildTargetExecutable(data.target)); 277 | else 278 | s += ".zip"; 279 | return s; 280 | } 281 | 282 | public static string ConvertBuildTargetToString(BuildTarget target) { 283 | switch (target) { 284 | case BuildTarget.StandaloneOSX: 285 | return "OSX"; 286 | case BuildTarget.StandaloneWindows: 287 | return "Windows32"; 288 | case BuildTarget.StandaloneWindows64: 289 | return "Windows64"; 290 | case BuildTarget.StandaloneLinux64: 291 | return "Linux"; 292 | } 293 | return target.ToString(); 294 | } 295 | 296 | public static string GetProductName() { 297 | return PlayerSettings.productName 298 | .Replace(' ', '_') 299 | .Replace('/', '_') 300 | .Replace('\\', '_') 301 | .Replace(':', '_') 302 | .Replace('*', '_') 303 | .Replace('?', '_') 304 | .Replace('"', '_') 305 | .Replace('<', '_') 306 | .Replace('>', '_') 307 | .Replace('|', '_') 308 | ; 309 | } 310 | 311 | public static string GetBuildTargetExecutable(BuildTarget target) { 312 | switch (target) { 313 | case BuildTarget.StandaloneWindows: 314 | case BuildTarget.StandaloneWindows64: 315 | return ".exe"; 316 | 317 | case BuildTarget.StandaloneLinux64: 318 | return ".x86_64"; 319 | 320 | case BuildTarget.StandaloneOSX: 321 | return ""; 322 | 323 | case BuildTarget.iOS: 324 | return ".ipa"; 325 | 326 | case BuildTarget.Android: 327 | return ".apk"; 328 | 329 | case BuildTarget.WebGL: 330 | return ""; 331 | } 332 | return ""; 333 | } 334 | #endregion 335 | 336 | #region Base methods 337 | static string BaseBuild(BuildTargetGroup buildTargetGroup, BuildTarget buildTarget, BuildOptions buildOptions, string buildPath, string definesSymbols, bool isPassbyBuild, bool isReleaseBuild) { 338 | if (isPassbyBuild) { 339 | return buildPath; 340 | } 341 | 342 | if (buildTarget == BuildTarget.Android && PlayerSettings.Android.useCustomKeystore && string.IsNullOrEmpty(PlayerSettings.Android.keyaliasPass)) { 343 | PlayerSettings.Android.keyaliasPass = PlayerSettings.Android.keystorePass = "keystore"; 344 | } 345 | 346 | if (isReleaseBuild) { 347 | switch (buildTargetGroup) { 348 | case BuildTargetGroup.Standalone: 349 | buildOptions |= BuildOptions.CompressWithLz4; 350 | 351 | if (buildTarget == BuildTarget.StandaloneWindows || buildTarget == BuildTarget.StandaloneWindows64 || buildTarget == BuildTarget.StandaloneLinux64) 352 | PlayerSettings.SetScriptingBackend(buildTargetGroup, ScriptingImplementation.IL2CPP); 353 | else 354 | PlayerSettings.SetScriptingBackend(buildTargetGroup, ScriptingImplementation.Mono2x); 355 | PlayerSettings.SetIl2CppCompilerConfiguration(buildTargetGroup, Il2CppCompilerConfiguration.Master); 356 | break; 357 | case BuildTargetGroup.Android: 358 | buildOptions |= BuildOptions.CompressWithLz4; 359 | 360 | PlayerSettings.SetScriptingBackend(buildTargetGroup, ScriptingImplementation.IL2CPP); 361 | PlayerSettings.SetIl2CppCompilerConfiguration(buildTargetGroup, Il2CppCompilerConfiguration.Master); 362 | 363 | PlayerSettings.Android.targetArchitectures = AndroidArchitecture.All; 364 | break; 365 | case BuildTargetGroup.WebGL: 366 | PlayerSettings.SetIl2CppCompilerConfiguration(buildTargetGroup, Il2CppCompilerConfiguration.Master); 367 | break; 368 | default: 369 | Debug.LogWarning($"{buildTargetGroup} is unsupported for release builds. No optimizations applied"); 370 | break; 371 | } 372 | } 373 | else { 374 | switch (buildTargetGroup) { 375 | case BuildTargetGroup.Standalone: 376 | buildOptions &= ~(BuildOptions.CompressWithLz4 | BuildOptions.CompressWithLz4HC); 377 | 378 | PlayerSettings.SetScriptingBackend(buildTargetGroup, ScriptingImplementation.Mono2x); 379 | PlayerSettings.SetIl2CppCompilerConfiguration(buildTargetGroup, Il2CppCompilerConfiguration.Debug); 380 | break; 381 | case BuildTargetGroup.Android: 382 | buildOptions &= ~(BuildOptions.CompressWithLz4 | BuildOptions.CompressWithLz4HC); 383 | 384 | PlayerSettings.SetScriptingBackend(buildTargetGroup, ScriptingImplementation.Mono2x); 385 | PlayerSettings.SetIl2CppCompilerConfiguration(buildTargetGroup, Il2CppCompilerConfiguration.Debug); 386 | 387 | PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARMv7; 388 | break; 389 | case BuildTargetGroup.WebGL: 390 | PlayerSettings.SetIl2CppCompilerConfiguration(buildTargetGroup, Il2CppCompilerConfiguration.Debug); 391 | break; 392 | default: 393 | Debug.LogWarning($"{buildTargetGroup} is unsupported for debug builds. No optimizations applied"); 394 | break; 395 | } 396 | } 397 | 398 | BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions { 399 | scenes = EditorBuildSettings.scenes.Where(s => s.enabled).Select(s => s.path).ToArray(), 400 | locationPathName = buildPath, 401 | targetGroup = buildTargetGroup, 402 | target = buildTarget, 403 | options = buildOptions, 404 | }; 405 | 406 | PlayerSettings.SetScriptingDefineSymbolsForGroup(buildTargetGroup, definesSymbols); 407 | BuildReport report = BuildPipeline.BuildPlayer(buildPlayerOptions); 408 | BuildSummary summary = report.summary; 409 | 410 | if (summary.result == BuildResult.Succeeded) { 411 | Debug.Log($"{summary.platform} succeeded. \t Time: {string.Format("{0:mm\\:ss}", summary.totalTime)} \t Size: {summary.totalSize / 1048576} Mb"); 412 | } 413 | else if (summary.result == BuildResult.Failed) { 414 | Debug.Log( 415 | $"{summary.platform} failed. \t Time: {string.Format("{0:mm\\:ss}", summary.totalTime)} \t Size: {summary.totalSize / 1048576} Mb" + "\n" + 416 | $"Warnings: {summary.totalWarnings}" + "\n" + 417 | $"Errors: {summary.totalErrors}" 418 | ); 419 | } 420 | 421 | return summary.result == BuildResult.Succeeded ? buildPath : ""; 422 | } 423 | 424 | static void BaseCompress(string dirPath) { 425 | using (ZipFile zip = new ZipFile()) { 426 | DateTime startTime = DateTime.Now; 427 | if (Directory.Exists(dirPath)) 428 | zip.AddDirectory(dirPath); 429 | else 430 | zip.AddFile(dirPath); 431 | zip.Save(dirPath + ".zip"); 432 | 433 | long uncompresedSize = 0; 434 | long compresedSize = 0; 435 | foreach (var e in zip.Entries) { 436 | uncompresedSize += e.UncompressedSize; 437 | compresedSize += e.CompressedSize; 438 | } 439 | Debug.Log($"Make {dirPath}.zip. \t Time: {string.Format("{0:mm\\:ss}", DateTime.Now - startTime)} \t Size: {uncompresedSize / 1048576} Mb - {compresedSize / 1048576} Mb"); 440 | } 441 | } 442 | 443 | static void PushItch(BuildManagerSettings settings, BuildSequence sequence, BuildData data) { 444 | StringBuilder fileName = new StringBuilder(128); 445 | StringBuilder args = new StringBuilder(128); 446 | 447 | 448 | string butlerPath = Application.dataPath + "/" + butlerRelativePath; 449 | if (!File.Exists(butlerPath)) { 450 | Debug.LogWarning("Butler not found."); 451 | DownloadButler(); 452 | } 453 | 454 | fileName.Append(butlerPath); 455 | 456 | args.Append(" push \""); 457 | args.Append(Application.dataPath); 458 | args.Append("/../"); 459 | args.Append(data.outputRoot + GetPathWithVars(data, data.dirPathForPostProcess)); 460 | args.Append("\" "); 461 | 462 | args.Append($"{settings.itchGameLink}:{data.itchChannel} "); 463 | args.Append($"--userversion \"{buildNameString}\" "); 464 | 465 | Debug.Log(fileName.ToString() + args.ToString()); 466 | Process.Start(fileName.ToString(), args.ToString()); 467 | } 468 | 469 | static void CreateGitHubReleaseIfNeeded(BuildManagerSettings settings, BuildSequence sequence) { 470 | for (byte i = 0; i < sequence.builds.Count; ++i) { 471 | if (!sequence.builds[i].isEnabled || !sequence.builds[i].needGithubPush) 472 | continue; 473 | 474 | if (string.IsNullOrEmpty(settings.GithubToken) || string.IsNullOrEmpty(settings.githubUserName) || string.IsNullOrEmpty(settings.githubRepoName)) { 475 | Debug.LogWarning($"Can't create github release. Required data is missing"); 476 | return; 477 | } 478 | 479 | CreateGitHubRelease(settings); 480 | break; 481 | } 482 | } 483 | 484 | static void CreateGitHubRelease(BuildManagerSettings settings) { 485 | StringBuilder fileName = new StringBuilder(128); 486 | StringBuilder args = new StringBuilder(128); 487 | 488 | string githubReleaseExe = Application.dataPath + "/" + githubReleasesRelativePath; 489 | if (!File.Exists(githubReleaseExe)) { 490 | Debug.LogWarning("GitHub release not found."); 491 | DownloadGithubRelease(); 492 | } 493 | 494 | fileName.Append(githubReleaseExe); 495 | args.Append(" release "); 496 | args.Append($"--security-token \"{settings.GithubToken}\" "); 497 | args.Append($"--user {settings.githubUserName} "); 498 | args.Append($"--repo {settings.githubRepoName} "); 499 | args.Append($"--tag v{PlayerSettings.bundleVersion} "); 500 | args.Append($"--name \"{buildNameString}\" "); 501 | args.Append($"--description \"{usedChangelog.GetLastChangelogString()}\" "); 502 | 503 | Debug.Log(fileName.ToString() + args.ToString()); 504 | Process.Start(fileName.ToString(), args.ToString()); 505 | } 506 | 507 | static void PushGithub(BuildManagerSettings settings, BuildSequence sequence, BuildData data) { 508 | StringBuilder fileName = new StringBuilder(128); 509 | StringBuilder args = new StringBuilder(128); 510 | 511 | string githubReleaseExe = Application.dataPath + "/" + githubReleasesRelativePath; 512 | 513 | fileName.Append(githubReleaseExe); 514 | 515 | args.Append(" upload "); 516 | args.Append($"--security-token \"{settings.GithubToken}\" "); 517 | args.Append($"--user {settings.githubUserName} "); 518 | args.Append($"--auth-user {settings.githubUserName} "); 519 | args.Append($"--repo {settings.githubRepoName} "); 520 | args.Append($"--tag v{PlayerSettings.bundleVersion} "); 521 | args.Append($"--name \"{GetPathWithVars(data, data.dirPathForPostProcess)}\" "); //download file name 522 | args.Append($"--label \"{GetPathWithVars(data, data.dirPathForPostProcess)}\" "); //name in releases 523 | args.Append($"--file \"{Path.Combine(Application.dataPath, "..", data.outputRoot, GetPathWithVarsForZip(data, data.dirPathForPostProcess)).Replace("\\", "/")}\" "); 524 | args.Append($"--replace "); 525 | 526 | Debug.Log(fileName.ToString() + args.ToString()); 527 | 528 | ProcessStartInfo info = new ProcessStartInfo(fileName.ToString(), args.ToString()) { 529 | UseShellExecute = false, 530 | RedirectStandardOutput = true, 531 | RedirectStandardError = true 532 | }; 533 | Process.Start(info); 534 | } 535 | #endregion 536 | 537 | #region Helpers 538 | static void ShowExplorer(string itemPath) { 539 | itemPath = itemPath.Replace(@"/", @"\"); // explorer doesn't like front slashes 540 | 541 | bool findFile = false; 542 | DirectoryInfo di = new DirectoryInfo(itemPath); 543 | foreach (FileInfo fi in di.GetFiles()) { 544 | if (fi.Name != "." && fi.Name != ".." && fi.Name != "Thumbs.db") { 545 | itemPath = fi.FullName; 546 | findFile = true; 547 | break; 548 | } 549 | } 550 | 551 | if (!findFile) { 552 | foreach (DirectoryInfo fi in di.GetDirectories()) { 553 | if (fi.Name != "." && fi.Name != ".." && fi.Name != "Thumbs.db") { 554 | itemPath = fi.FullName; 555 | break; 556 | } 557 | } 558 | } 559 | 560 | Process.Start("explorer.exe", "/select," + itemPath); 561 | } 562 | 563 | static void CreateAllFodersBeforePath(string path) { 564 | string[] dirs = ("Assets/" + path).Split('/'); 565 | string allPath = dirs[0]; 566 | for (int i = 1; i < dirs.Length - 1; ++i) { 567 | if (!AssetDatabase.IsValidFolder(allPath + "/" + dirs[i])) { 568 | AssetDatabase.CreateFolder(allPath, dirs[i]); 569 | } 570 | allPath = allPath + "/" + dirs[i]; 571 | } 572 | } 573 | #endregion 574 | 575 | #region Download CLI 576 | [MenuItem("Window/BuildManager/Download butler(itch.io)")] 577 | public static void DownloadButler() { 578 | using (var client = new WebClient()) { 579 | Debug.Log("Downloading butler..."); 580 | 581 | string butlerPath = Application.dataPath + "/" + butlerRelativePath; 582 | string butlerDirPath = butlerPath.Replace("butler.exe", ""); 583 | string zipPath = butlerPath.Replace("butler.exe", "butler.zip"); 584 | 585 | CreateAllFodersBeforePath(butlerRelativePath); 586 | 587 | client.DownloadFile(butlerDownloadPath, zipPath); 588 | 589 | using (ZipFile zip = ZipFile.Read(zipPath)) { 590 | foreach (ZipEntry e in zip) { 591 | e.Extract(butlerDirPath, ExtractExistingFileAction.OverwriteSilently); 592 | } 593 | } 594 | 595 | File.Delete(zipPath); 596 | } 597 | } 598 | 599 | [MenuItem("Window/BuildManager/Download github-release(github.com)")] 600 | public static void DownloadGithubRelease() { 601 | using (var client = new WebClient()) { 602 | Debug.Log("Downloading github-release..."); 603 | 604 | string exePath = Application.dataPath + "/" + githubReleasesRelativePath; 605 | string dirPath = exePath.Replace("github-release.exe", ""); 606 | string zipPath = exePath.Replace("github-release.exe", "windows-amd64-github-release.zip"); 607 | 608 | CreateAllFodersBeforePath(githubReleasesRelativePath); 609 | 610 | client.DownloadFile(githubReleasesDownloadPath, zipPath); 611 | 612 | using (ZipFile zip = ZipFile.Read(zipPath)) { 613 | foreach (ZipEntry e in zip) { 614 | e.Extract(dirPath, ExtractExistingFileAction.OverwriteSilently); 615 | } 616 | } 617 | 618 | File.Copy(Path.Combine(dirPath, "bin", "windows", "amd64", "github-release.exe"), exePath); 619 | Directory.Delete(Path.Combine(dirPath, "bin"), true); 620 | File.Delete(zipPath); 621 | } 622 | } 623 | #endregion 624 | } 625 | -------------------------------------------------------------------------------- /Editor/BuildManager/BuildPipeline/BuildManager.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 28614fe83e1139742914bc4f05a3e64b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/BuildManager/BuildPipeline/BuildManagerSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | 6 | public class BuildManagerSettings : ScriptableObject { 7 | public List sequences = new List() { new BuildSequence() }; 8 | 9 | public string scriptingDefineSymbols; 10 | 11 | public string itchGameLink; 12 | 13 | public string GithubToken { 14 | get { 15 | if(string.IsNullOrEmpty(githubToken)) 16 | githubToken = EditorPrefs.GetString("BuildManager.GitHub.Token", ""); 17 | return githubToken; 18 | } 19 | set { 20 | githubToken = value; 21 | EditorPrefs.SetString("BuildManager.GitHub.Token", githubToken); 22 | } 23 | } 24 | string githubToken; 25 | public string githubUserName; 26 | public string githubRepoName; 27 | 28 | public void CloneInto(BuildManagerSettings settings) { 29 | scriptingDefineSymbols = settings.scriptingDefineSymbols; 30 | 31 | sequences = new List(settings.sequences.Count); 32 | for(int i = 0; i < settings.sequences.Count; ++i) { 33 | sequences.Add(settings.sequences[i].Clone() as BuildSequence); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Editor/BuildManager/BuildPipeline/BuildManagerSettings.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bf73a4e20e61f9143863e020e3cfa443 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/BuildManager/BuildPipeline/BuildSequence.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | 6 | 7 | [Serializable] 8 | public class BuildSequence : ICloneable { 9 | public bool isEnabled; 10 | 11 | public string editorName; 12 | 13 | public string scriptingDefineSymbolsOverride; 14 | 15 | public List builds = new List() { new BuildData() }; 16 | 17 | public BuildSequence() : this("New build sequence", new BuildData()) { 18 | } 19 | 20 | public BuildSequence(string editorName, params BuildData[] builds) { 21 | this.editorName = editorName; 22 | this.builds = new List(builds); 23 | 24 | scriptingDefineSymbolsOverride = ""; 25 | 26 | isEnabled = true; 27 | } 28 | 29 | public object Clone() { 30 | BuildSequence sequence = this.MemberwiseClone() as BuildSequence; 31 | 32 | sequence.builds = new List(builds.Count); 33 | for (int i = 0; i < builds.Count; ++i) { 34 | sequence.builds.Add(builds[i].Clone() as BuildData); 35 | } 36 | 37 | return sequence; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Editor/BuildManager/BuildPipeline/BuildSequence.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7da761c09c9bf58458414eb3aed17661 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/BuildManager/DefaultBuildSequences.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: bf73a4e20e61f9143863e020e3cfa443, type: 3} 13 | m_Name: DefaultBuildSequences 14 | m_EditorClassIdentifier: 15 | sequences: 16 | - isEnabled: 1 17 | editorName: Testing 18 | scriptingDefineSymbolsOverride: 19 | builds: 20 | - isEnabled: 1 21 | outputRoot: Builds/ 22 | middlePath: $NAME_$PLATFORM/$NAME/$NAME$EXECUTABLE 23 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 24 | isPassbyBuild: 0 25 | scriptingDefineSymbolsOverride: 26 | targetGroup: 1 27 | target: 5 28 | options: 0 29 | isVirtualRealitySupported: 0 30 | isReleaseBuild: 0 31 | needZip: 0 32 | needItchPush: 0 33 | itchChannel: windows-32 34 | needGithubPush: 0 35 | needGamejolthPush: 0 36 | needSteamPush: 0 37 | needGoogleDrivePush: 0 38 | - isEnabled: 1 39 | outputRoot: Builds/ 40 | middlePath: $NAME_$PLATFORM/$NAME/$NAME$EXECUTABLE 41 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 42 | isPassbyBuild: 0 43 | scriptingDefineSymbolsOverride: 44 | targetGroup: 1 45 | target: 19 46 | options: 0 47 | isVirtualRealitySupported: 0 48 | isReleaseBuild: 0 49 | needZip: 0 50 | needItchPush: 0 51 | itchChannel: windows-64 52 | needGithubPush: 0 53 | needGamejolthPush: 0 54 | needSteamPush: 0 55 | needGoogleDrivePush: 0 56 | - isEnabled: 1 57 | outputRoot: Builds/ 58 | middlePath: $NAME_$PLATFORM/$NAME/$NAME$EXECUTABLE 59 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 60 | isPassbyBuild: 0 61 | scriptingDefineSymbolsOverride: 62 | targetGroup: 1 63 | target: 24 64 | options: 0 65 | isVirtualRealitySupported: 0 66 | isReleaseBuild: 0 67 | needZip: 0 68 | needItchPush: 0 69 | itchChannel: linux-universal 70 | needGithubPush: 0 71 | needGamejolthPush: 0 72 | needSteamPush: 0 73 | needGoogleDrivePush: 0 74 | - isEnabled: 1 75 | outputRoot: Builds/ 76 | middlePath: $NAME_$PLATFORM/$NAME/$NAME$EXECUTABLE 77 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 78 | isPassbyBuild: 0 79 | scriptingDefineSymbolsOverride: 80 | targetGroup: 1 81 | target: 2 82 | options: 0 83 | isVirtualRealitySupported: 0 84 | isReleaseBuild: 0 85 | needZip: 0 86 | needItchPush: 0 87 | itchChannel: osx-universal 88 | needGithubPush: 0 89 | needGamejolthPush: 0 90 | needSteamPush: 0 91 | needGoogleDrivePush: 0 92 | - isEnabled: 1 93 | outputRoot: Builds/ 94 | middlePath: $NAME_$PLATFORM/ 95 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 96 | isPassbyBuild: 0 97 | scriptingDefineSymbolsOverride: 98 | targetGroup: 13 99 | target: 20 100 | options: 0 101 | isVirtualRealitySupported: 0 102 | isReleaseBuild: 0 103 | needZip: 0 104 | needItchPush: 0 105 | itchChannel: webgl 106 | needGithubPush: 0 107 | needGamejolthPush: 0 108 | needSteamPush: 0 109 | needGoogleDrivePush: 0 110 | - isEnabled: 1 111 | outputRoot: Builds/ 112 | middlePath: $NAME_$PLATFORM$EXECUTABLE 113 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 114 | isPassbyBuild: 0 115 | scriptingDefineSymbolsOverride: 116 | targetGroup: 7 117 | target: 13 118 | options: 0 119 | isVirtualRealitySupported: 0 120 | isReleaseBuild: 0 121 | needZip: 0 122 | needItchPush: 0 123 | itchChannel: android 124 | needGithubPush: 0 125 | needGamejolthPush: 0 126 | needSteamPush: 0 127 | needGoogleDrivePush: 0 128 | - isEnabled: 1 129 | editorName: Testing + zip 130 | scriptingDefineSymbolsOverride: 131 | builds: 132 | - isEnabled: 1 133 | outputRoot: Builds/ 134 | middlePath: $NAME_$PLATFORM/$NAME/$NAME$EXECUTABLE 135 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 136 | isPassbyBuild: 0 137 | scriptingDefineSymbolsOverride: 138 | targetGroup: 1 139 | target: 5 140 | options: 0 141 | isVirtualRealitySupported: 0 142 | isReleaseBuild: 0 143 | needZip: 1 144 | needItchPush: 0 145 | itchChannel: windows-32 146 | needGithubPush: 0 147 | needGamejolthPush: 0 148 | needSteamPush: 0 149 | needGoogleDrivePush: 0 150 | - isEnabled: 1 151 | outputRoot: Builds/ 152 | middlePath: $NAME_$PLATFORM/$NAME/$NAME$EXECUTABLE 153 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 154 | isPassbyBuild: 0 155 | scriptingDefineSymbolsOverride: 156 | targetGroup: 1 157 | target: 19 158 | options: 0 159 | isVirtualRealitySupported: 0 160 | isReleaseBuild: 0 161 | needZip: 1 162 | needItchPush: 0 163 | itchChannel: windows-64 164 | needGithubPush: 0 165 | needGamejolthPush: 0 166 | needSteamPush: 0 167 | needGoogleDrivePush: 0 168 | - isEnabled: 1 169 | outputRoot: Builds/ 170 | middlePath: $NAME_$PLATFORM/$NAME/$NAME$EXECUTABLE 171 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 172 | isPassbyBuild: 0 173 | scriptingDefineSymbolsOverride: 174 | targetGroup: 1 175 | target: 24 176 | options: 0 177 | isVirtualRealitySupported: 0 178 | isReleaseBuild: 0 179 | needZip: 1 180 | needItchPush: 0 181 | itchChannel: linux-universal 182 | needGithubPush: 0 183 | needGamejolthPush: 0 184 | needSteamPush: 0 185 | needGoogleDrivePush: 0 186 | - isEnabled: 1 187 | outputRoot: Builds/ 188 | middlePath: $NAME_$PLATFORM/$NAME/$NAME$EXECUTABLE 189 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 190 | isPassbyBuild: 0 191 | scriptingDefineSymbolsOverride: 192 | targetGroup: 1 193 | target: 2 194 | options: 0 195 | isVirtualRealitySupported: 0 196 | isReleaseBuild: 0 197 | needZip: 1 198 | needItchPush: 0 199 | itchChannel: osx-universal 200 | needGithubPush: 0 201 | needGamejolthPush: 0 202 | needSteamPush: 0 203 | needGoogleDrivePush: 0 204 | - isEnabled: 1 205 | outputRoot: Builds/ 206 | middlePath: $NAME_$PLATFORM/ 207 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 208 | isPassbyBuild: 0 209 | scriptingDefineSymbolsOverride: 210 | targetGroup: 13 211 | target: 20 212 | options: 0 213 | isVirtualRealitySupported: 0 214 | isReleaseBuild: 0 215 | needZip: 1 216 | needItchPush: 0 217 | itchChannel: webgl 218 | needGithubPush: 0 219 | needGamejolthPush: 0 220 | needSteamPush: 0 221 | needGoogleDrivePush: 0 222 | - isEnabled: 1 223 | outputRoot: Builds/ 224 | middlePath: $NAME_$PLATFORM$EXECUTABLE 225 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 226 | isPassbyBuild: 0 227 | scriptingDefineSymbolsOverride: 228 | targetGroup: 7 229 | target: 13 230 | options: 0 231 | isVirtualRealitySupported: 0 232 | isReleaseBuild: 0 233 | needZip: 1 234 | needItchPush: 0 235 | itchChannel: android 236 | needGithubPush: 0 237 | needGamejolthPush: 0 238 | needSteamPush: 0 239 | needGoogleDrivePush: 0 240 | - isEnabled: 1 241 | editorName: Passby local release 242 | scriptingDefineSymbolsOverride: 243 | builds: 244 | - isEnabled: 1 245 | outputRoot: Builds/Releases/ 246 | middlePath: $NAME_$VERSION_$PLATFORM/$NAME_$VERSION/$NAME$EXECUTABLE 247 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 248 | isPassbyBuild: 1 249 | scriptingDefineSymbolsOverride: 250 | targetGroup: 1 251 | target: 5 252 | options: 0 253 | isVirtualRealitySupported: 0 254 | isReleaseBuild: 1 255 | needZip: 1 256 | needItchPush: 1 257 | itchChannel: windows-32 258 | needGithubPush: 0 259 | needGamejolthPush: 0 260 | needSteamPush: 0 261 | needGoogleDrivePush: 0 262 | - isEnabled: 1 263 | outputRoot: Builds/Releases/ 264 | middlePath: $NAME_$VERSION_$PLATFORM/$NAME_$VERSION/$NAME$EXECUTABLE 265 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 266 | isPassbyBuild: 1 267 | scriptingDefineSymbolsOverride: 268 | targetGroup: 1 269 | target: 19 270 | options: 0 271 | isVirtualRealitySupported: 0 272 | isReleaseBuild: 1 273 | needZip: 1 274 | needItchPush: 1 275 | itchChannel: windows-64 276 | needGithubPush: 0 277 | needGamejolthPush: 0 278 | needSteamPush: 0 279 | needGoogleDrivePush: 0 280 | - isEnabled: 1 281 | outputRoot: Builds/Releases/ 282 | middlePath: $NAME_$VERSION_$PLATFORM/$NAME_$VERSION/$NAME$EXECUTABLE 283 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 284 | isPassbyBuild: 1 285 | scriptingDefineSymbolsOverride: 286 | targetGroup: 1 287 | target: 24 288 | options: 0 289 | isVirtualRealitySupported: 0 290 | isReleaseBuild: 1 291 | needZip: 1 292 | needItchPush: 1 293 | itchChannel: linux-universal 294 | needGithubPush: 0 295 | needGamejolthPush: 0 296 | needSteamPush: 0 297 | needGoogleDrivePush: 0 298 | - isEnabled: 1 299 | outputRoot: Builds/Releases/ 300 | middlePath: $NAME_$VERSION_$PLATFORM/$NAME_$VERSION/$NAME$EXECUTABLE 301 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 302 | isPassbyBuild: 1 303 | scriptingDefineSymbolsOverride: 304 | targetGroup: 1 305 | target: 2 306 | options: 0 307 | isVirtualRealitySupported: 0 308 | isReleaseBuild: 1 309 | needZip: 1 310 | needItchPush: 1 311 | itchChannel: osx-universal 312 | needGithubPush: 0 313 | needGamejolthPush: 0 314 | needSteamPush: 0 315 | needGoogleDrivePush: 0 316 | - isEnabled: 1 317 | outputRoot: Builds/Releases/ 318 | middlePath: $NAME_$VERSION_$PLATFORM/ 319 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 320 | isPassbyBuild: 1 321 | scriptingDefineSymbolsOverride: 322 | targetGroup: 13 323 | target: 20 324 | options: 0 325 | isVirtualRealitySupported: 0 326 | isReleaseBuild: 1 327 | needZip: 1 328 | needItchPush: 1 329 | itchChannel: webgl 330 | needGithubPush: 0 331 | needGamejolthPush: 0 332 | needSteamPush: 0 333 | needGoogleDrivePush: 0 334 | - isEnabled: 1 335 | outputRoot: Builds/Releases/ 336 | middlePath: $NAME_$VERSION_$PLATFORM$EXECUTABLE 337 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 338 | isPassbyBuild: 1 339 | scriptingDefineSymbolsOverride: 340 | targetGroup: 7 341 | target: 13 342 | options: 0 343 | isVirtualRealitySupported: 0 344 | isReleaseBuild: 1 345 | needZip: 1 346 | needItchPush: 1 347 | itchChannel: android 348 | needGithubPush: 0 349 | needGamejolthPush: 0 350 | needSteamPush: 0 351 | needGoogleDrivePush: 0 352 | - isEnabled: 1 353 | editorName: Release 354 | scriptingDefineSymbolsOverride: 355 | builds: 356 | - isEnabled: 1 357 | outputRoot: Builds/Releases/ 358 | middlePath: $NAME_$VERSION_$PLATFORM/$NAME_$VERSION/$NAME$EXECUTABLE 359 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 360 | isPassbyBuild: 0 361 | scriptingDefineSymbolsOverride: 362 | targetGroup: 1 363 | target: 5 364 | options: 0 365 | isVirtualRealitySupported: 0 366 | isReleaseBuild: 1 367 | needZip: 0 368 | needItchPush: 0 369 | itchChannel: windows-32 370 | needGithubPush: 0 371 | needGamejolthPush: 0 372 | needSteamPush: 0 373 | needGoogleDrivePush: 0 374 | - isEnabled: 1 375 | outputRoot: Builds/Releases/ 376 | middlePath: $NAME_$VERSION_$PLATFORM/$NAME_$VERSION/$NAME$EXECUTABLE 377 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 378 | isPassbyBuild: 0 379 | scriptingDefineSymbolsOverride: 380 | targetGroup: 1 381 | target: 19 382 | options: 0 383 | isVirtualRealitySupported: 0 384 | isReleaseBuild: 1 385 | needZip: 0 386 | needItchPush: 0 387 | itchChannel: windows-64 388 | needGithubPush: 0 389 | needGamejolthPush: 0 390 | needSteamPush: 0 391 | needGoogleDrivePush: 0 392 | - isEnabled: 1 393 | outputRoot: Builds/Releases/ 394 | middlePath: $NAME_$VERSION_$PLATFORM/$NAME_$VERSION/$NAME$EXECUTABLE 395 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 396 | isPassbyBuild: 0 397 | scriptingDefineSymbolsOverride: 398 | targetGroup: 1 399 | target: 24 400 | options: 0 401 | isVirtualRealitySupported: 0 402 | isReleaseBuild: 1 403 | needZip: 0 404 | needItchPush: 0 405 | itchChannel: linux-universal 406 | needGithubPush: 0 407 | needGamejolthPush: 0 408 | needSteamPush: 0 409 | needGoogleDrivePush: 0 410 | - isEnabled: 1 411 | outputRoot: Builds/Releases/ 412 | middlePath: $NAME_$VERSION_$PLATFORM/$NAME_$VERSION/$NAME$EXECUTABLE 413 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 414 | isPassbyBuild: 0 415 | scriptingDefineSymbolsOverride: 416 | targetGroup: 1 417 | target: 2 418 | options: 0 419 | isVirtualRealitySupported: 0 420 | isReleaseBuild: 1 421 | needZip: 0 422 | needItchPush: 0 423 | itchChannel: osx-universal 424 | needGithubPush: 0 425 | needGamejolthPush: 0 426 | needSteamPush: 0 427 | needGoogleDrivePush: 0 428 | - isEnabled: 1 429 | outputRoot: Builds/Releases/ 430 | middlePath: $NAME_$VERSION_$PLATFORM/ 431 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 432 | isPassbyBuild: 0 433 | scriptingDefineSymbolsOverride: 434 | targetGroup: 13 435 | target: 20 436 | options: 0 437 | isVirtualRealitySupported: 0 438 | isReleaseBuild: 1 439 | needZip: 0 440 | needItchPush: 0 441 | itchChannel: webgl 442 | needGithubPush: 0 443 | needGamejolthPush: 0 444 | needSteamPush: 0 445 | needGoogleDrivePush: 0 446 | - isEnabled: 1 447 | outputRoot: Builds/Releases/ 448 | middlePath: $NAME_$VERSION_$PLATFORM$EXECUTABLE 449 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 450 | isPassbyBuild: 0 451 | scriptingDefineSymbolsOverride: 452 | targetGroup: 7 453 | target: 13 454 | options: 0 455 | isVirtualRealitySupported: 0 456 | isReleaseBuild: 1 457 | needZip: 0 458 | needItchPush: 0 459 | itchChannel: android 460 | needGithubPush: 0 461 | needGamejolthPush: 0 462 | needSteamPush: 0 463 | needGoogleDrivePush: 0 464 | - isEnabled: 1 465 | editorName: Release + zip 466 | scriptingDefineSymbolsOverride: 467 | builds: 468 | - isEnabled: 1 469 | outputRoot: Builds/Releases/ 470 | middlePath: $NAME_$VERSION_$PLATFORM/$NAME_$VERSION/$NAME$EXECUTABLE 471 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 472 | isPassbyBuild: 0 473 | scriptingDefineSymbolsOverride: 474 | targetGroup: 1 475 | target: 5 476 | options: 0 477 | isVirtualRealitySupported: 0 478 | isReleaseBuild: 1 479 | needZip: 1 480 | needItchPush: 0 481 | itchChannel: windows-32 482 | needGithubPush: 0 483 | needGamejolthPush: 0 484 | needSteamPush: 0 485 | needGoogleDrivePush: 0 486 | - isEnabled: 1 487 | outputRoot: Builds/Releases/ 488 | middlePath: $NAME_$VERSION_$PLATFORM/$NAME_$VERSION/$NAME$EXECUTABLE 489 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 490 | isPassbyBuild: 0 491 | scriptingDefineSymbolsOverride: 492 | targetGroup: 1 493 | target: 19 494 | options: 0 495 | isVirtualRealitySupported: 0 496 | isReleaseBuild: 1 497 | needZip: 1 498 | needItchPush: 0 499 | itchChannel: windows-64 500 | needGithubPush: 0 501 | needGamejolthPush: 0 502 | needSteamPush: 0 503 | needGoogleDrivePush: 0 504 | - isEnabled: 1 505 | outputRoot: Builds/Releases/ 506 | middlePath: $NAME_$VERSION_$PLATFORM/$NAME_$VERSION/$NAME$EXECUTABLE 507 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 508 | isPassbyBuild: 0 509 | scriptingDefineSymbolsOverride: 510 | targetGroup: 1 511 | target: 24 512 | options: 0 513 | isVirtualRealitySupported: 0 514 | isReleaseBuild: 1 515 | needZip: 1 516 | needItchPush: 0 517 | itchChannel: linux-universal 518 | needGithubPush: 0 519 | needGamejolthPush: 0 520 | needSteamPush: 0 521 | needGoogleDrivePush: 0 522 | - isEnabled: 1 523 | outputRoot: Builds/Releases/ 524 | middlePath: $NAME_$VERSION_$PLATFORM/$NAME_$VERSION/$NAME$EXECUTABLE 525 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 526 | isPassbyBuild: 0 527 | scriptingDefineSymbolsOverride: 528 | targetGroup: 1 529 | target: 2 530 | options: 0 531 | isVirtualRealitySupported: 0 532 | isReleaseBuild: 1 533 | needZip: 1 534 | needItchPush: 0 535 | itchChannel: osx-universal 536 | needGithubPush: 0 537 | needGamejolthPush: 0 538 | needSteamPush: 0 539 | needGoogleDrivePush: 0 540 | - isEnabled: 1 541 | outputRoot: Builds/Releases/ 542 | middlePath: $NAME_$VERSION_$PLATFORM/ 543 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 544 | isPassbyBuild: 0 545 | scriptingDefineSymbolsOverride: 546 | targetGroup: 13 547 | target: 20 548 | options: 0 549 | isVirtualRealitySupported: 0 550 | isReleaseBuild: 1 551 | needZip: 1 552 | needItchPush: 0 553 | itchChannel: webgl 554 | needGithubPush: 0 555 | needGamejolthPush: 0 556 | needSteamPush: 0 557 | needGoogleDrivePush: 0 558 | - isEnabled: 1 559 | outputRoot: Builds/Releases/ 560 | middlePath: $NAME_$VERSION_$PLATFORM$EXECUTABLE 561 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 562 | isPassbyBuild: 0 563 | scriptingDefineSymbolsOverride: 564 | targetGroup: 7 565 | target: 13 566 | options: 0 567 | isVirtualRealitySupported: 0 568 | isReleaseBuild: 1 569 | needZip: 1 570 | needItchPush: 0 571 | itchChannel: android 572 | needGithubPush: 0 573 | needGamejolthPush: 0 574 | needSteamPush: 0 575 | needGoogleDrivePush: 0 576 | - isEnabled: 1 577 | editorName: Release full 578 | scriptingDefineSymbolsOverride: 579 | builds: 580 | - isEnabled: 1 581 | outputRoot: Builds/Releases/ 582 | middlePath: $NAME_$VERSION_$PLATFORM/$NAME_$VERSION/$NAME$EXECUTABLE 583 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 584 | isPassbyBuild: 0 585 | scriptingDefineSymbolsOverride: 586 | targetGroup: 1 587 | target: 5 588 | options: 0 589 | isVirtualRealitySupported: 0 590 | isReleaseBuild: 1 591 | needZip: 1 592 | needItchPush: 1 593 | itchChannel: windows-32 594 | needGithubPush: 1 595 | needGamejolthPush: 0 596 | needSteamPush: 0 597 | needGoogleDrivePush: 0 598 | - isEnabled: 1 599 | outputRoot: Builds/Releases/ 600 | middlePath: $NAME_$VERSION_$PLATFORM/$NAME_$VERSION/$NAME$EXECUTABLE 601 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 602 | isPassbyBuild: 0 603 | scriptingDefineSymbolsOverride: 604 | targetGroup: 1 605 | target: 19 606 | options: 0 607 | isVirtualRealitySupported: 0 608 | isReleaseBuild: 1 609 | needZip: 1 610 | needItchPush: 1 611 | itchChannel: windows-64 612 | needGithubPush: 1 613 | needGamejolthPush: 0 614 | needSteamPush: 0 615 | needGoogleDrivePush: 0 616 | - isEnabled: 1 617 | outputRoot: Builds/Releases/ 618 | middlePath: $NAME_$VERSION_$PLATFORM/$NAME_$VERSION/$NAME$EXECUTABLE 619 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 620 | isPassbyBuild: 0 621 | scriptingDefineSymbolsOverride: 622 | targetGroup: 1 623 | target: 24 624 | options: 0 625 | isVirtualRealitySupported: 0 626 | isReleaseBuild: 1 627 | needZip: 1 628 | needItchPush: 1 629 | itchChannel: linux-universal 630 | needGithubPush: 1 631 | needGamejolthPush: 0 632 | needSteamPush: 0 633 | needGoogleDrivePush: 0 634 | - isEnabled: 1 635 | outputRoot: Builds/Releases/ 636 | middlePath: $NAME_$VERSION_$PLATFORM/$NAME_$VERSION/$NAME$EXECUTABLE 637 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 638 | isPassbyBuild: 0 639 | scriptingDefineSymbolsOverride: 640 | targetGroup: 1 641 | target: 2 642 | options: 0 643 | isVirtualRealitySupported: 0 644 | isReleaseBuild: 1 645 | needZip: 1 646 | needItchPush: 1 647 | itchChannel: osx-universal 648 | needGithubPush: 1 649 | needGamejolthPush: 0 650 | needSteamPush: 0 651 | needGoogleDrivePush: 0 652 | - isEnabled: 1 653 | outputRoot: Builds/Releases/ 654 | middlePath: $NAME_$VERSION_$PLATFORM/ 655 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 656 | isPassbyBuild: 0 657 | scriptingDefineSymbolsOverride: 658 | targetGroup: 13 659 | target: 20 660 | options: 0 661 | isVirtualRealitySupported: 0 662 | isReleaseBuild: 1 663 | needZip: 1 664 | needItchPush: 1 665 | itchChannel: webgl 666 | needGithubPush: 1 667 | needGamejolthPush: 0 668 | needSteamPush: 0 669 | needGoogleDrivePush: 0 670 | - isEnabled: 1 671 | outputRoot: Builds/Releases/ 672 | middlePath: $NAME_$VERSION_$PLATFORM$EXECUTABLE 673 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 674 | isPassbyBuild: 0 675 | scriptingDefineSymbolsOverride: 676 | targetGroup: 7 677 | target: 13 678 | options: 0 679 | isVirtualRealitySupported: 0 680 | isReleaseBuild: 1 681 | needZip: 1 682 | needItchPush: 1 683 | itchChannel: android 684 | needGithubPush: 1 685 | needGamejolthPush: 0 686 | needSteamPush: 0 687 | needGoogleDrivePush: 0 688 | - isEnabled: 1 689 | editorName: Testing win only 690 | scriptingDefineSymbolsOverride: 691 | builds: 692 | - isEnabled: 1 693 | outputRoot: Builds/ 694 | middlePath: $NAME_TEST/$NAME$EXECUTABLE 695 | dirPathForPostProcess: $NAME_$VERSION_$PLATFORM 696 | isPassbyBuild: 1 697 | scriptingDefineSymbolsOverride: 698 | targetGroup: 1 699 | target: 5 700 | options: 0 701 | isVirtualRealitySupported: 0 702 | isReleaseBuild: 0 703 | needZip: 1 704 | needItchPush: 0 705 | itchChannel: windows-testing 706 | needGithubPush: 1 707 | needGamejolthPush: 0 708 | needSteamPush: 0 709 | needGoogleDrivePush: 0 710 | scriptingDefineSymbols: 711 | itchGameLink: teamon/BuildManagerUPM 712 | githubUserName: Team-on 713 | githubRepoName: BuildManagerUPM 714 | -------------------------------------------------------------------------------- /Editor/BuildManager/DefaultBuildSequences.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bb50a83f6a8fb0b4abc31ab1ddbae5ee 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/BuildManager/DotNetZip.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-on/UnityBuildManager/5ccccffd24b63fdfe65d45a02362e5798e941ee1/Editor/BuildManager/DotNetZip.dll -------------------------------------------------------------------------------- /Editor/BuildManager/DotNetZip.dll.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5e527d3d7babb6d49b32c03ac3133acf 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | defineConstraints: [] 9 | isPreloaded: 0 10 | isOverridable: 0 11 | isExplicitlyReferenced: 0 12 | validateReferences: 1 13 | platformData: 14 | - first: 15 | Any: 16 | second: 17 | enabled: 0 18 | settings: {} 19 | - first: 20 | Editor: Editor 21 | second: 22 | enabled: 1 23 | settings: 24 | DefaultValueInitialized: true 25 | - first: 26 | Windows Store Apps: WindowsStoreApps 27 | second: 28 | enabled: 0 29 | settings: 30 | CPU: AnyCPU 31 | userData: 32 | assetBundleName: 33 | assetBundleVariant: 34 | -------------------------------------------------------------------------------- /Editor/Changelog.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b2a9e68f5a6ddca45b194d667d34a96a 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Changelog/ChangelogData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using UnityEngine; 7 | using UnityEditor; 8 | 9 | [Serializable] 10 | public class ChangelogData { 11 | 12 | public List versions = new List() { new ChangelogVersionEntry() }; 13 | [TextArea(3, 10)] public string readme; 14 | 15 | public ChangelogVersionEntry GetLastVersion() { 16 | if (versions.Count == 0) 17 | return new ChangelogVersionEntry(); 18 | return versions[versions.Count - 1]; 19 | } 20 | 21 | public string GetChangelogString() { 22 | StringBuilder sb = new StringBuilder(); 23 | 24 | sb.Append("Note: 📢 indicates a change inspired by community feedback!\n"); 25 | 26 | for (int i = versions.Count - 1; i >= 0; --i) { 27 | versions[i].GetChangelog(ref sb); 28 | } 29 | 30 | return sb.ToString(); 31 | } 32 | 33 | public string GetLastChangelogString() { 34 | StringBuilder sb = new StringBuilder(); 35 | sb.Append("Note: 📢 indicates a change inspired by community feedback!\n"); 36 | versions[versions.Count - 1].GetChangelog(ref sb); 37 | return sb.ToString(); 38 | } 39 | 40 | 41 | #region Serialization 42 | const string SAVE_FILE_NOREZ = "ChangelogSettings"; 43 | const string SAVE_FILE = "ChangelogSettings.json"; 44 | const string SAVE_FILE_EDITORPREFS = "ChangelogSettings.Save"; 45 | const string SAVE_FILE_EDITORPREFS_DEFAULT = "Editor/Setting/ChangelogSettings.json"; 46 | 47 | public static void SaveChangelog(ChangelogData data) { 48 | if (!PlayerPrefs.HasKey(SAVE_FILE_EDITORPREFS)) { 49 | string[] allPath = AssetDatabase.FindAssets(SAVE_FILE_NOREZ); 50 | if (allPath.Length != 0) 51 | PlayerPrefs.SetString(SAVE_FILE_EDITORPREFS, AssetDatabase.GUIDToAssetPath(allPath[0]).Replace("Assets/", "")); 52 | } 53 | 54 | string savePath = Path.Combine(Application.dataPath, PlayerPrefs.GetString(SAVE_FILE_EDITORPREFS, SAVE_FILE_EDITORPREFS_DEFAULT)); 55 | 56 | string json = JsonUtility.ToJson(data, true); 57 | 58 | if (!File.Exists(savePath)) { 59 | FileInfo file = new FileInfo(savePath); 60 | file.Directory.Create(); 61 | } 62 | 63 | File.WriteAllText(savePath, json); 64 | } 65 | 66 | public static ChangelogData LoadChangelog() { 67 | if (!PlayerPrefs.HasKey(SAVE_FILE_EDITORPREFS)) { 68 | string[] allPath = AssetDatabase.FindAssets(SAVE_FILE_NOREZ); 69 | if (allPath.Length != 0) 70 | PlayerPrefs.SetString(SAVE_FILE_EDITORPREFS, AssetDatabase.GUIDToAssetPath(allPath[0]).Replace("Assets/", "")); 71 | } 72 | 73 | string savePath = Path.Combine(Application.dataPath, PlayerPrefs.GetString(SAVE_FILE_EDITORPREFS, SAVE_FILE_EDITORPREFS_DEFAULT)); 74 | 75 | if (!File.Exists(savePath)) { 76 | return new ChangelogData(); 77 | } 78 | else { 79 | string json = File.ReadAllText(savePath); 80 | return JsonUtility.FromJson(json); 81 | } 82 | } 83 | #endregion 84 | 85 | [Serializable] 86 | public class ChangelogVersionEntry { 87 | [NonSerialized] public bool foldout = false; 88 | 89 | public string version; 90 | public string date; 91 | public string updateName; 92 | 93 | public string descriptionText; 94 | 95 | public List notes = new List(); 96 | 97 | public string GetVersionHeader() { 98 | string header; 99 | 100 | if (!string.IsNullOrEmpty(updateName) && !string.IsNullOrEmpty(date)) { 101 | header = $"{version} - {updateName} ({date})"; 102 | } 103 | else if (!string.IsNullOrEmpty(updateName)) { 104 | header = $"{version} - {updateName}"; 105 | } 106 | else if (!string.IsNullOrEmpty(date)) { 107 | header = $"{version} ({date})"; 108 | } 109 | else { 110 | header = $"{version}"; 111 | } 112 | 113 | return header; 114 | } 115 | 116 | public void GetChangelog(ref StringBuilder sb) { 117 | ChangelogEntryType lastType = (ChangelogEntryType)255; 118 | ChangelogEntryScope lastScope = (ChangelogEntryScope)255; 119 | 120 | sb.Append("\n\n---------- \n"); 121 | sb.Append("# "); 122 | sb.Append(GetVersionHeader()); 123 | sb.Append("\n"); 124 | 125 | sb.Append(descriptionText); 126 | sb.Append("\n"); 127 | 128 | for (int j = 0; j < notes.Count; ++j) { 129 | if (lastType != notes[j].type) { 130 | if (lastType != (ChangelogEntryType)255) 131 | sb.Append("\n"); 132 | lastType = notes[j].type; 133 | lastScope = (ChangelogEntryScope)255; 134 | sb.Append("### "); 135 | sb.Append(notes[j].type); 136 | sb.Append(": \n"); 137 | } 138 | 139 | if (lastScope != notes[j].scope) { 140 | lastScope = notes[j].scope; 141 | sb.Append("#### "); 142 | sb.Append(notes[j].scope); 143 | sb.Append(": \n"); 144 | } 145 | 146 | notes[j].GetChangelog(ref sb); 147 | } 148 | } 149 | } 150 | 151 | [Serializable] 152 | public class ChangelogNoteEntry { 153 | public bool isCommunityFeedback = false; 154 | public ChangelogEntryType type; 155 | public ChangelogEntryScope scope; 156 | public string text; 157 | 158 | public void GetChangelog(ref StringBuilder sb) { 159 | sb.Append(" * "); 160 | if (isCommunityFeedback) 161 | sb.Append("📢 "); 162 | sb.Append(text); 163 | sb.Append("\n"); 164 | } 165 | } 166 | 167 | public enum ChangelogEntryType : byte { 168 | General = 0, 169 | Docs = 1, 170 | Features = 2, 171 | Fixes = 3, 172 | Optimizations = 4, 173 | Improvements = 5, 174 | Changes = 6, 175 | Refactoring = 7, 176 | Testing = 8, 177 | KnownIssues = 9, 178 | } 179 | 180 | public enum ChangelogEntryScope : byte { 181 | General = 0, 182 | Gameplay = 1, 183 | LevelDesign = 2, 184 | Art = 3, 185 | VFX = 4, 186 | UI = 5, 187 | Music = 6, 188 | SFX = 7, 189 | Voice = 8, 190 | Narrative = 9, 191 | Miscellaneous = 10, 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /Editor/Changelog/ChangelogData.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a640640e60731e2428771e6284750784 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Window.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0a6923b9c4dc3c54cb2b35dbacd397e5 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Window/BuildDataReordableList.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | using UnityEditor; 4 | 5 | public class BuildDataReordableList { 6 | public static UnityEditorInternal.ReorderableList Create(List configsList, GenericMenu.MenuFunction2 menuItemHandler, string header) { 7 | var reorderableList = new UnityEditorInternal.ReorderableList(configsList, typeof(BuildData), true, false, true, true); 8 | 9 | reorderableList.elementHeight = EditorGUIUtility.singleLineHeight + 4; 10 | reorderableList.drawHeaderCallback = (Rect rect) => { EditorGUI.LabelField(rect, header); }; 11 | reorderableList.drawElementCallback = (position, index, isActive, isFocused) => { 12 | const float enabledWidth = 15f; 13 | const float buildTargetGroupWidth = 125f; 14 | const float buildTargetWidth = 150f; 15 | const float minbuildOptionsWidth = 100f; 16 | const float space = 10f; 17 | 18 | float buildOptionsWidth = position.width - space * 6 - enabledWidth - buildTargetWidth - buildTargetGroupWidth; 19 | if (buildOptionsWidth < minbuildOptionsWidth) 20 | buildOptionsWidth = minbuildOptionsWidth; 21 | 22 | BuildData data = configsList[index]; 23 | 24 | position.y += 2; 25 | position.height -= 4; 26 | 27 | position.x += space; 28 | position.width = enabledWidth; 29 | data.isEnabled = EditorGUI.Toggle(position, data.isEnabled); 30 | EditorGUI.BeginDisabledGroup(!data.isEnabled); 31 | 32 | position.x += position.width + space; 33 | position.width = buildTargetGroupWidth; 34 | data.targetGroup = (BuildTargetGroup)EditorGUI.EnumPopup(position, data.targetGroup); 35 | 36 | position.x += position.width + space; 37 | position.width = buildTargetWidth; 38 | data.target = (BuildTarget)EditorGUI.EnumPopup(position, data.target); 39 | 40 | position.x += position.width + space; 41 | position.width = buildOptionsWidth; 42 | data.options = (BuildOptions)EditorGUI.EnumFlagsField(position, data.options); 43 | 44 | EditorGUI.EndDisabledGroup(); 45 | }; 46 | 47 | reorderableList.onAddDropdownCallback = (buttonRect, list) => { 48 | var menu = new GenericMenu(); 49 | 50 | menu.AddItem(new GUIContent("Custom"), false, menuItemHandler, new BuildData()); 51 | menu.AddSeparator(""); 52 | 53 | foreach (BuildData config in PredefinedBuildConfigs.standaloneData) { 54 | var label = /*"Standalone/" +*/ BuildManager.ConvertBuildTargetToString(config.target); 55 | menu.AddItem(new GUIContent(label), false, menuItemHandler, config); 56 | } 57 | menu.AddSeparator(""); 58 | 59 | foreach (BuildData config in PredefinedBuildConfigs.androidData) { 60 | var label = /*"Android/" +*/ BuildManager.ConvertBuildTargetToString(config.target); 61 | menu.AddItem(new GUIContent(label), false, menuItemHandler, config); 62 | } 63 | menu.AddSeparator(""); 64 | 65 | foreach (BuildData config in PredefinedBuildConfigs.webData) { 66 | var label = /*"WebGL/"+ */ BuildManager.ConvertBuildTargetToString(config.target); 67 | menu.AddItem(new GUIContent(label), false, menuItemHandler, config); 68 | } 69 | menu.AddSeparator(""); 70 | 71 | 72 | menu.ShowAsContext(); 73 | }; 74 | 75 | return reorderableList; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Editor/Window/BuildDataReordableList.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 07aece2e7f958e64a9cca251191341c3 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Window/BuildManagerWindow.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using UnityEngine; 3 | using UnityEditor; 4 | using UnityEditorInternal; 5 | 6 | public class BuildManagerWindow : EditorWindow { 7 | const string SETTINGS_DEFAULT_PATH = "Assets/Editor/Setting/BuildSequences.asset"; //Need Assets in path, cuz used by AssetDatabase.CreateAsset 8 | const string SETTINGS_PATH_KEY = "BuildManagerWindow.SettingsPath"; 9 | 10 | static string settingsPath; 11 | static BuildManagerSettings settings; 12 | 13 | static bool globalDataFoldout = true; 14 | 15 | static ChangelogData changelog; 16 | static bool changelogFoldout = false; 17 | static Vector2 scrollPosChangelog = Vector2.zero; 18 | 19 | static Vector2 scrollPosSequence = Vector2.zero; 20 | static bool postBuildFoldout = false; 21 | 22 | static ReorderableList sequenceList; 23 | static ReorderableList buildList; 24 | 25 | [MenuItem("Window/BuildManager/Builds window &b")] 26 | public static void ShowWindow() { 27 | sequenceList = null; 28 | buildList = null; 29 | GetWindow(typeof(BuildManagerWindow), false, "Builds", true); 30 | 31 | LoadSettings(); 32 | } 33 | 34 | void OnGUI() { 35 | if (settings == null) 36 | LoadSettings(); 37 | if (changelog == null) 38 | LoadChangelog(); 39 | 40 | DrawGlobalBuildData(); 41 | DrawChangelogInfo(); 42 | 43 | if (!changelogFoldout) { 44 | DrawBuildButtons(); 45 | 46 | EditorGUILayout.Space(20); 47 | scrollPosSequence = EditorGUILayout.BeginScrollView(scrollPosSequence); 48 | 49 | DrawSequenceList(); 50 | DrawSelectedSequenceData(); 51 | 52 | EditorGUILayout.EndScrollView(); 53 | } 54 | else { 55 | EditorGUILayout.HelpBox("Close changelog to acess build data", MessageType.Warning); 56 | } 57 | 58 | EditorUtility.SetDirty(settings); 59 | } 60 | 61 | #region Main Drawers 62 | void DrawGlobalBuildData() { 63 | globalDataFoldout = EditorGUILayout.BeginFoldoutHeaderGroup(globalDataFoldout, "Global data"); 64 | if (globalDataFoldout) { 65 | ++EditorGUI.indentLevel; 66 | 67 | //Versions 68 | PlayerSettings.companyName = EditorGUILayout.TextField("Company Name", PlayerSettings.companyName); 69 | PlayerSettings.productName = EditorGUILayout.TextField("Product Name", PlayerSettings.productName); 70 | PlayerSettings.bundleVersion = EditorGUILayout.TextField("Version", PlayerSettings.bundleVersion); 71 | PlayerSettings.Android.bundleVersionCode = EditorGUILayout.IntField("Android bundle version", PlayerSettings.Android.bundleVersionCode); 72 | 73 | //Defines 74 | GUILayout.Space(5); 75 | EditorGUILayout.BeginHorizontal(); 76 | settings.scriptingDefineSymbols = EditorGUILayout.TextField("Scripting Defines", settings.scriptingDefineSymbols); 77 | if (GUILayout.Button($"Set defines", GUILayout.Width(100f))) 78 | PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget), settings.scriptingDefineSymbols); 79 | EditorGUILayout.EndHorizontal(); 80 | 81 | //Itch data 82 | GUILayout.Space(5); 83 | EditorGUILayout.BeginHorizontal(); 84 | settings.itchGameLink = EditorGUILayout.TextField("Itch.io link", settings.itchGameLink); 85 | if (string.IsNullOrEmpty(settings.itchGameLink)) 86 | settings.itchGameLink = $"teamon/{BuildManager.GetProductName()}"; 87 | if (GUILayout.Button($"Open", GUILayout.Width(100f))) { 88 | int slashId = settings.itchGameLink.IndexOf("/"); 89 | string name = settings.itchGameLink.Substring(0, slashId); 90 | string game = settings.itchGameLink.Substring(slashId + 1); 91 | Application.OpenURL($"https://{name}.itch.io/{game}"); 92 | } 93 | if (GUILayout.Button($"Docs", GUILayout.Width(100f))) { 94 | Application.OpenURL($"https://itch.io/docs/butler/pushing.html"); 95 | } 96 | EditorGUILayout.EndHorizontal(); 97 | 98 | //Github data 99 | GUILayout.Space(5); 100 | EditorGUILayout.BeginHorizontal(); 101 | settings.GithubToken = EditorGUILayout.TextField("Github token", settings.GithubToken); 102 | if (GUILayout.Button($"Generate", GUILayout.Width(100f))) 103 | Application.OpenURL($"https://github.com/settings/tokens"); 104 | if (GUILayout.Button($"Docs", GUILayout.Width(100f))) 105 | Application.OpenURL($"https://github.com/github-release/github-release"); 106 | EditorGUILayout.EndHorizontal(); 107 | 108 | EditorGUILayout.BeginHorizontal(); 109 | settings.githubUserName = EditorGUILayout.TextField("Github user name", settings.githubUserName); 110 | if (string.IsNullOrEmpty(settings.githubUserName)) 111 | settings.githubUserName = $"Team-on"; 112 | if (GUILayout.Button($"Open", GUILayout.Width(100f))) 113 | Application.OpenURL($"https://github.com/{settings.githubUserName}"); 114 | EditorGUILayout.EndHorizontal(); 115 | 116 | EditorGUILayout.BeginHorizontal(); 117 | settings.githubRepoName = EditorGUILayout.TextField("Github repo name", settings.githubRepoName); 118 | if (string.IsNullOrEmpty(settings.githubRepoName)) 119 | settings.githubRepoName = BuildManager.GetProductName(); 120 | if (GUILayout.Button($"Open", GUILayout.Width(100f))) 121 | Application.OpenURL($"https://github.com/{settings.githubUserName}/{settings.githubRepoName}"); 122 | EditorGUILayout.EndHorizontal(); 123 | 124 | 125 | --EditorGUI.indentLevel; 126 | } 127 | EditorGUILayout.EndFoldoutHeaderGroup(); 128 | 129 | if (globalDataFoldout) 130 | EditorGUILayout.Space(20); 131 | } 132 | 133 | void DrawChangelogInfo() { 134 | bool oldChangelogFoldoutValue = changelogFoldout; 135 | changelogFoldout = EditorGUILayout.BeginFoldoutHeaderGroup(changelogFoldout, "Changelog"); 136 | EditorGUILayout.EndFoldoutHeaderGroup(); 137 | 138 | if (changelogFoldout) { 139 | scrollPosChangelog = EditorGUILayout.BeginScrollView(scrollPosChangelog/*, GUILayout.Height(800f)*/); 140 | ++EditorGUI.indentLevel; 141 | 142 | EditorGUILayout.LabelField("Readme"); 143 | changelog.readme = EditorGUILayout.TextArea(changelog.readme); 144 | GUILayout.Space(10f); 145 | 146 | EditorGUILayout.BeginHorizontal(); 147 | EditorGUILayout.LabelField("Changelog file:", GUILayout.Width(100)); 148 | if (GUILayout.Button($"Add version")) 149 | changelog.versions.Add(new ChangelogData.ChangelogVersionEntry()); 150 | EditorGUILayout.EndHorizontal(); 151 | 152 | for (int i = changelog.versions.Count - 1; i >= 0; --i) { 153 | ChangelogData.ChangelogVersionEntry version = changelog.versions[i]; 154 | 155 | EditorGUILayout.BeginHorizontal(); 156 | version.foldout = EditorGUILayout.BeginFoldoutHeaderGroup(version.foldout, $"{version.version} - {version.date}"); 157 | EditorGUILayout.EndFoldoutHeaderGroup(); 158 | if (GUILayout.Button($"Remove version", GUILayout.Width(100))) { 159 | changelog.versions.RemoveAt(i); 160 | return; 161 | } 162 | EditorGUILayout.EndHorizontal(); 163 | 164 | if (string.IsNullOrEmpty(version.version)) 165 | version.version = PlayerSettings.bundleVersion; 166 | if (string.IsNullOrEmpty(version.date)) 167 | version.date = System.DateTime.Now.ToShortDateString(); 168 | 169 | if (version.foldout) { 170 | ++EditorGUI.indentLevel; 171 | 172 | EditorGUILayout.BeginHorizontal(); 173 | version.version = EditorGUILayout.TextField("Version", version.version); 174 | if (GUILayout.Button($"Curr", GUILayout.Width(70))) 175 | version.version = PlayerSettings.bundleVersion; 176 | EditorGUILayout.EndHorizontal(); 177 | 178 | EditorGUILayout.BeginHorizontal(); 179 | version.date = EditorGUILayout.TextField("Date", version.date); 180 | if (GUILayout.Button($"Now", GUILayout.Width(70))) 181 | version.date = System.DateTime.Now.ToShortDateString(); 182 | EditorGUILayout.EndHorizontal(); 183 | 184 | version.updateName = EditorGUILayout.TextField("Update name", version.updateName); 185 | version.descriptionText = EditorGUILayout.TextField("Description", version.descriptionText); 186 | 187 | EditorGUILayout.LabelField("Notes: "); 188 | 189 | ++EditorGUI.indentLevel; 190 | EditorGUILayout.BeginHorizontal(); 191 | EditorGUILayout.LabelField("Type", GUILayout.Width(150)); 192 | EditorGUILayout.LabelField("Scope", GUILayout.Width(125)); 193 | EditorGUILayout.LabelField("Community", GUILayout.Width(100)); 194 | EditorGUILayout.LabelField("Description"); 195 | EditorGUILayout.EndHorizontal(); 196 | 197 | for (int j = 0; j < version.notes.Count; ++j) { 198 | ChangelogData.ChangelogNoteEntry note = version.notes[j]; 199 | EditorGUILayout.BeginHorizontal(); 200 | 201 | ChangelogData.ChangelogEntryType newType = (ChangelogData.ChangelogEntryType)EditorGUILayout.EnumPopup(note.type, GUILayout.Width(150)); 202 | ChangelogData.ChangelogEntryScope newScope = (ChangelogData.ChangelogEntryScope)EditorGUILayout.EnumPopup(note.scope, GUILayout.Width(150)); 203 | note.isCommunityFeedback = EditorGUILayout.Toggle(note.isCommunityFeedback, GUILayout.Width(70)); 204 | note.text = EditorGUILayout.TextField(note.text); 205 | 206 | if (note.type != newType || note.scope != newScope) { 207 | note.type = newType; 208 | note.scope = newScope; 209 | version.notes = version.notes.OrderBy(_note => _note.type).ThenBy(_note => _note.scope).ToList(); 210 | return; 211 | } 212 | 213 | if (GUILayout.Button($"-", GUILayout.Width(25))) { 214 | version.notes.RemoveAt(j); 215 | return; 216 | } 217 | 218 | EditorGUILayout.EndHorizontal(); 219 | } 220 | --EditorGUI.indentLevel; 221 | 222 | if (GUILayout.Button($"Add note")) 223 | version.notes.Add(new ChangelogData.ChangelogNoteEntry()); 224 | 225 | --EditorGUI.indentLevel; 226 | } 227 | 228 | EditorGUILayout.Space(10); 229 | } 230 | 231 | --EditorGUI.indentLevel; 232 | EditorGUILayout.EndScrollView(); 233 | } 234 | 235 | if (oldChangelogFoldoutValue != changelogFoldout) { 236 | ChangelogData.SaveChangelog(changelog); 237 | 238 | #if GAME_TEMPLATE 239 | TemplateGameManager.Instance.buildNameString = changelog.GetLastVersion().GetVersionHeader();; 240 | TemplateGameManager.Instance.productName = PlayerSettings.productName; 241 | EditorUtility.SetDirty(TemplateGameManager.Instance); 242 | #endif 243 | } 244 | 245 | if (changelogFoldout) 246 | EditorGUILayout.Space(20); 247 | } 248 | 249 | void DrawBuildButtons() { 250 | if ((settings?.sequences?.Count ?? 0) != 0) { 251 | int enabledSequence = 0; 252 | foreach (var sequence in settings.sequences) 253 | if (sequence.isEnabled) 254 | ++enabledSequence; 255 | 256 | if (enabledSequence == 0) 257 | return; 258 | 259 | Color prevColor = GUI.backgroundColor; 260 | GUI.backgroundColor = new Color(0.773f, 0.345098f, 0.345098f); 261 | 262 | EditorGUILayout.LabelField("Start build sequence(they red not becouse error, but becouse build stuck your pc if you accidentaly press it)"); 263 | EditorGUILayout.LabelField("Don't forget to manually download new version of polyglot localization if you want to update it"); 264 | 265 | EditorGUILayout.BeginHorizontal(); 266 | for (int i = 0; i < settings.sequences.Count; ++i) { 267 | BuildSequence sequence = settings.sequences[i]; 268 | 269 | if (i != 0 && i % 3 == 0) { 270 | EditorGUILayout.EndHorizontal(); 271 | EditorGUILayout.BeginHorizontal(); 272 | } 273 | 274 | if (sequence.isEnabled && GUILayout.Button($"Build {sequence.editorName}")) { 275 | BuildManager.RunBuildSequnce(settings, sequence, changelog); 276 | } 277 | } 278 | EditorGUILayout.EndHorizontal(); 279 | 280 | GUI.backgroundColor = prevColor; 281 | } 282 | } 283 | 284 | void DrawSequenceList() { 285 | if (sequenceList == null) { 286 | PredefinedBuildConfigs.Init(); 287 | sequenceList = BuildSequenceReordableList.Create(settings.sequences, OnSequenceAdd, "Builds sequences"); 288 | sequenceList.onSelectCallback += OnSequenceSelectionChanged; 289 | sequenceList.index = 0; 290 | } 291 | 292 | sequenceList.DoLayoutList(); 293 | 294 | if (0 <= sequenceList.index && sequenceList.index < sequenceList.count) { 295 | BuildSequence selected = settings.sequences[sequenceList.index]; 296 | 297 | EditorGUILayout.BeginHorizontal(); 298 | selected.scriptingDefineSymbolsOverride = EditorGUILayout.TextField("Defines sequence override", selected.scriptingDefineSymbolsOverride); 299 | if (GUILayout.Button($"Set defines", GUILayout.Width(100f))) { 300 | PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget), string.Concat(settings.scriptingDefineSymbols, ";", selected.scriptingDefineSymbolsOverride)); 301 | } 302 | EditorGUILayout.EndHorizontal(); 303 | } 304 | } 305 | 306 | void DrawSelectedSequenceData() { 307 | EditorGUILayout.Space(20); 308 | 309 | if (sequenceList.index < 0 || sequenceList.index >= settings.sequences.Count) { 310 | buildList = null; 311 | return; 312 | } 313 | 314 | if (buildList == null) { 315 | buildList = BuildDataReordableList.Create(settings.sequences[sequenceList.index].builds, OnBuildAdd, "Builds"); 316 | buildList.onSelectCallback += OnBuildSelectionChanged; ; 317 | buildList.index = 0; 318 | } 319 | 320 | buildList.DoLayoutList(); 321 | 322 | if (buildList.index < 0 || buildList.index >= settings.sequences[sequenceList.index].builds.Count) 323 | return; 324 | 325 | BuildData selected = settings.sequences[sequenceList.index].builds[buildList.index]; 326 | 327 | SerializedObject obj = new SerializedObject(settings); 328 | 329 | selected.isPassbyBuild = EditorGUILayout.Toggle("Is Passby build", selected.isPassbyBuild); 330 | selected.isReleaseBuild = EditorGUILayout.Toggle("Is Release build", selected.isReleaseBuild); 331 | selected.isVirtualRealitySupported = EditorGUILayout.Toggle("VR Supported", selected.isVirtualRealitySupported); 332 | 333 | EditorGUILayout.Space(20); 334 | selected.outputRoot = EditorGUILayout.TextField("Output root", selected.outputRoot); 335 | selected.middlePath = EditorGUILayout.TextField("Middle path", selected.middlePath); 336 | selected.dirPathForPostProcess = EditorGUILayout.TextField("Dir path", selected.dirPathForPostProcess); 337 | 338 | EditorGUILayout.BeginHorizontal(); 339 | selected.scriptingDefineSymbolsOverride = EditorGUILayout.TextField("Defines build override", selected.scriptingDefineSymbolsOverride); 340 | if (GUILayout.Button($"Set defines", GUILayout.Width(100f))) { 341 | PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget), string.Concat(settings.scriptingDefineSymbols, ";", settings.sequences[sequenceList.index].scriptingDefineSymbolsOverride, ";", selected.scriptingDefineSymbolsOverride)); 342 | } 343 | EditorGUILayout.EndHorizontal(); 344 | 345 | EditorGUILayout.Space(20); 346 | postBuildFoldout = EditorGUILayout.BeginFoldoutHeaderGroup(postBuildFoldout, "Post build processing"); 347 | if (postBuildFoldout) { 348 | ++EditorGUI.indentLevel; 349 | selected.needZip = EditorGUILayout.Toggle("Compress", selected.needZip); 350 | selected.needGithubPush = EditorGUILayout.Toggle("Push to github releases", selected.needGithubPush); 351 | if (selected.needGithubPush && !selected.needZip) { 352 | selected.needZip = true; 353 | Debug.Log(".zip must be created before pushing to GitHub releases"); 354 | } 355 | 356 | EditorGUILayout.LabelField("itch.io:"); 357 | ++EditorGUI.indentLevel; 358 | selected.needItchPush = EditorGUILayout.Toggle("Push to itch.io", selected.needItchPush); 359 | selected.itchChannel = EditorGUILayout.TextField("Channel", selected.itchChannel); 360 | --EditorGUI.indentLevel; 361 | 362 | --EditorGUI.indentLevel; 363 | } 364 | EditorGUILayout.EndFoldoutHeaderGroup(); 365 | } 366 | #endregion 367 | 368 | #region Loaders 369 | static void LoadSettings() { 370 | settingsPath = PlayerPrefs.GetString(SETTINGS_PATH_KEY, ""); 371 | settings = null; 372 | 373 | //Find path. Try to load settings 374 | if (!string.IsNullOrEmpty(settingsPath)) { 375 | settings = AssetDatabase.LoadAssetAtPath(settingsPath); 376 | if (settings == null) { 377 | settingsPath = null; 378 | } 379 | } 380 | 381 | //No path, or cant locate asset at path. Try to find settings in assets. 382 | if (string.IsNullOrEmpty(settingsPath)) { 383 | string[] guids = AssetDatabase.FindAssets("t:BuildManagerSettings", new string[] { "Assets" }); 384 | if (guids.Length >= 2) { 385 | Debug.LogError("[BuildManagerWindow]. 2+ BuildManagerSettings exist. Consider on using only 1 setting. The first one will be used."); 386 | } 387 | 388 | if (guids.Length != 0) { 389 | settingsPath = AssetDatabase.GUIDToAssetPath(guids[0]); 390 | PlayerPrefs.SetString(SETTINGS_PATH_KEY, settingsPath); 391 | settings = AssetDatabase.LoadAssetAtPath(settingsPath); 392 | } 393 | } 394 | 395 | //Cant find settings. Create new 396 | if (settings == null) { 397 | BuildManagerSettings defaultSettings = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(AssetDatabase.FindAssets("t:BuildManagerSettings", new string[] { "Packages" })[0])); 398 | 399 | settings = (BuildManagerSettings)ScriptableObject.CreateInstance(typeof(BuildManagerSettings)); 400 | settings.CloneInto(defaultSettings); 401 | 402 | AssetDatabase.CreateAsset(settings, SETTINGS_DEFAULT_PATH); 403 | settingsPath = SETTINGS_DEFAULT_PATH; 404 | PlayerPrefs.SetString(SETTINGS_PATH_KEY, SETTINGS_DEFAULT_PATH); 405 | } 406 | } 407 | 408 | static void LoadChangelog() { 409 | changelog = ChangelogData.LoadChangelog(); 410 | } 411 | 412 | #endregion 413 | 414 | #region Callbacks 415 | static void OnSequenceSelectionChanged(ReorderableList list) { 416 | buildList = null; 417 | } 418 | 419 | static void OnBuildSelectionChanged(ReorderableList list) { 420 | 421 | } 422 | 423 | static void OnSequenceAdd(object target) { 424 | settings.sequences.Add((target as BuildSequence).Clone() as BuildSequence); 425 | } 426 | 427 | static void OnBuildAdd(object target) { 428 | settings.sequences[sequenceList.index].builds.Add((target as BuildData).Clone() as BuildData); 429 | } 430 | 431 | #endregion 432 | 433 | #region Helpers 434 | void GuiLine(int i_height = 1) { 435 | Rect rect = EditorGUILayout.GetControlRect(false, i_height); 436 | rect.height = i_height; 437 | EditorGUI.DrawRect(rect, new Color(0.5f, 0.5f, 0.5f, 1)); 438 | } 439 | #endregion 440 | } 441 | -------------------------------------------------------------------------------- /Editor/Window/BuildManagerWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 87f16f47c7bb98c47b2570bbc67ce3a1 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Window/BuildSequenceReordableList.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | using UnityEditor; 4 | 5 | public class BuildSequenceReordableList { 6 | public static UnityEditorInternal.ReorderableList Create(List configsList, GenericMenu.MenuFunction2 menuItemHandler, string header) { 7 | var reorderableList = new UnityEditorInternal.ReorderableList(configsList, typeof(BuildSequence), true, false, true, true); 8 | 9 | reorderableList.elementHeight = EditorGUIUtility.singleLineHeight + 4; 10 | reorderableList.drawHeaderCallback = (Rect rect) => { EditorGUI.LabelField(rect, header); }; 11 | reorderableList.drawElementCallback = (position, index, isActive, isFocused) => { 12 | const float enabledWidth = 15f; 13 | const float space = 10f; 14 | const float minNameWidth = 100f; 15 | 16 | BuildSequence sequence = configsList[index]; 17 | var nameWidth = position.width - space * 3 - enabledWidth; 18 | if (nameWidth < minNameWidth) 19 | nameWidth = minNameWidth; 20 | 21 | position.y += 2; 22 | position.height -= 4; 23 | 24 | position.x += space; 25 | position.width = enabledWidth; 26 | sequence.isEnabled = EditorGUI.Toggle(position, sequence.isEnabled); 27 | EditorGUI.BeginDisabledGroup(!sequence.isEnabled); 28 | 29 | position.x += position.width + space; 30 | position.width = nameWidth; 31 | sequence.editorName = EditorGUI.TextField(position, sequence.editorName); 32 | 33 | EditorGUI.EndDisabledGroup(); 34 | }; 35 | 36 | reorderableList.onAddDropdownCallback = (buttonRect, list) => { 37 | var menu = new GenericMenu(); 38 | 39 | menu.AddItem(new GUIContent("Custom"), false, menuItemHandler, new BuildSequence("Custom", new BuildData())); 40 | menu.AddSeparator(""); 41 | 42 | string label = $"{PredefinedBuildConfigs.testingSequence.editorName}"; 43 | menu.AddItem(new GUIContent(label), false, menuItemHandler, PredefinedBuildConfigs.testingSequence); 44 | 45 | label = $"{PredefinedBuildConfigs.testingSequenceZip.editorName}"; 46 | menu.AddItem(new GUIContent(label), false, menuItemHandler, PredefinedBuildConfigs.testingSequenceZip); 47 | 48 | 49 | menu.AddSeparator(""); 50 | label = $"{PredefinedBuildConfigs.releaseLocalSequence.editorName}"; 51 | menu.AddItem(new GUIContent(label), false, menuItemHandler, PredefinedBuildConfigs.releaseLocalSequence); 52 | 53 | label = $"{PredefinedBuildConfigs.releaseLocalZipSequence.editorName}"; 54 | menu.AddItem(new GUIContent(label), false, menuItemHandler, PredefinedBuildConfigs.releaseLocalZipSequence); 55 | 56 | label = $"{PredefinedBuildConfigs.releaseFullSequence.editorName}"; 57 | menu.AddItem(new GUIContent(label), false, menuItemHandler, PredefinedBuildConfigs.releaseFullSequence); 58 | 59 | 60 | menu.AddSeparator(""); 61 | label = $"{PredefinedBuildConfigs.passbySequence.editorName}"; 62 | menu.AddItem(new GUIContent(label), false, menuItemHandler, PredefinedBuildConfigs.passbySequence); 63 | 64 | 65 | menu.ShowAsContext(); 66 | }; 67 | 68 | return reorderableList; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Editor/Window/BuildSequenceReordableList.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bc7cf623d3caea34a89eb28e4482463d 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Window/PredefinedBuildConfigs.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEditor; 3 | 4 | public static class PredefinedBuildConfigs { 5 | public static BuildSequence testingSequence; 6 | public static BuildSequence testingSequenceZip; 7 | 8 | public static BuildSequence releaseLocalSequence; 9 | public static BuildSequence releaseLocalZipSequence; 10 | public static BuildSequence releaseFullSequence; 11 | 12 | public static BuildSequence passbySequence; 13 | 14 | public static BuildData[] standaloneData = new BuildData[] { 15 | new BuildData(BuildTargetGroup.Standalone, BuildTarget.StandaloneWindows){ itchChannel = "windows-32" }, 16 | new BuildData(BuildTargetGroup.Standalone, BuildTarget.StandaloneWindows64){ itchChannel = "windows-64" }, 17 | new BuildData(BuildTargetGroup.Standalone, BuildTarget.StandaloneLinux64){ itchChannel = "linux-universal" }, 18 | new BuildData(BuildTargetGroup.Standalone, BuildTarget.StandaloneOSX){ itchChannel = "osx-universal" }, 19 | }; 20 | 21 | public static BuildData[] webData = new BuildData[] { 22 | new BuildData(BuildTargetGroup.WebGL, BuildTarget.WebGL){ middlePath = "$NAME_$VERSION_$PLATFORM/", itchChannel = "webgl"}, 23 | }; 24 | 25 | public static BuildData[] androidData = new BuildData[] { 26 | new BuildData(BuildTargetGroup.Android, BuildTarget.Android){ middlePath = "$NAME_$VERSION_$PLATFORM$EXECUTABLE", dirPathForPostProcess = "$NAME_$VERSION_$PLATFORM$EXECUTABLE", itchChannel = "android"}, 27 | }; 28 | 29 | public static void Init() { 30 | List dataOriginal = new List(); 31 | List data = new List(); 32 | 33 | foreach (BuildData buildData in standaloneData) { 34 | dataOriginal.Add(buildData.Clone() as BuildData); 35 | } 36 | foreach (BuildData buildData in webData) { 37 | dataOriginal.Add(buildData.Clone() as BuildData); 38 | } 39 | foreach (BuildData buildData in androidData) { 40 | dataOriginal.Add(buildData.Clone() as BuildData); 41 | } 42 | 43 | FillTestingSequence(ref dataOriginal, ref data); 44 | FillReleaseSequence(ref dataOriginal, ref data); 45 | } 46 | 47 | static void FillTestingSequence(ref List dataOriginal, ref List data) { 48 | for (int i = 0; i < dataOriginal.Count; ++i) { 49 | data.Add(dataOriginal[i].Clone() as BuildData); 50 | data[i].middlePath = data[i].middlePath.Replace("_$VERSION", ""); 51 | data[i].dirPathForPostProcess = data[i].dirPathForPostProcess.Replace("_$VERSION", ""); 52 | } 53 | testingSequence = new BuildSequence("Testing", data.ToArray()); 54 | data.Clear(); 55 | 56 | for (int i = 0; i < dataOriginal.Count; ++i) { 57 | data.Add(dataOriginal[i].Clone() as BuildData); 58 | data[i].needZip = true; 59 | data[i].middlePath = data[i].middlePath.Replace("_$VERSION", ""); 60 | data[i].dirPathForPostProcess = data[i].dirPathForPostProcess.Replace("_$VERSION", ""); 61 | } 62 | testingSequenceZip = new BuildSequence("Testing + zip", data.ToArray()); 63 | data.Clear(); 64 | } 65 | 66 | static void FillReleaseSequence(ref List dataOriginal, ref List data) { 67 | for (int i = 0; i < dataOriginal.Count; ++i) { 68 | dataOriginal[i].outputRoot += "Releases/"; 69 | } 70 | 71 | for (int i = 0; i < dataOriginal.Count; ++i) { 72 | data.Add(dataOriginal[i].Clone() as BuildData); 73 | data[i].isReleaseBuild = true; 74 | } 75 | releaseLocalSequence = new BuildSequence("Release", data.ToArray()); 76 | data.Clear(); 77 | 78 | for (int i = 0; i < dataOriginal.Count; ++i) { 79 | data.Add(dataOriginal[i].Clone() as BuildData); 80 | data[i].isReleaseBuild = true; 81 | data[i].needZip = true; 82 | } 83 | releaseLocalZipSequence = new BuildSequence("Release + zip", data.ToArray()); 84 | data.Clear(); 85 | 86 | for (int i = 0; i < dataOriginal.Count; ++i) { 87 | data.Add(dataOriginal[i].Clone() as BuildData); 88 | data[i].isReleaseBuild = true; 89 | data[i].needZip = true; 90 | data[i].needItchPush = true; 91 | data[i].needGithubPush = true; 92 | } 93 | releaseFullSequence = new BuildSequence("Release full", data.ToArray()); 94 | data.Clear(); 95 | 96 | for (int i = 0; i < dataOriginal.Count; ++i) { 97 | data.Add(dataOriginal[i].Clone() as BuildData); 98 | data[i].isReleaseBuild = true; 99 | data[i].isPassbyBuild = true; 100 | data[i].needZip = true; 101 | data[i].needItchPush = true; 102 | data[i].needGithubPush = true; 103 | } 104 | passbySequence = new BuildSequence("Passby local release", data.ToArray()); 105 | data.Clear(); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Editor/Window/PredefinedBuildConfigs.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 590e3b114e6c01a408a92bb4f19c373c 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /HelpScreenshots.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: beb089ccf1c0baf40a85daf4d4c8ee5b 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /HelpScreenshots/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-on/UnityBuildManager/5ccccffd24b63fdfe65d45a02362e5798e941ee1/HelpScreenshots/1.png -------------------------------------------------------------------------------- /HelpScreenshots/1.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6120dcfb0de019d41877069aefdb204a 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | vTOnly: 0 27 | grayScaleToAlpha: 0 28 | generateCubemap: 6 29 | cubemapConvolution: 0 30 | seamlessCubemap: 0 31 | textureFormat: 1 32 | maxTextureSize: 2048 33 | textureSettings: 34 | serializedVersion: 2 35 | filterMode: -1 36 | aniso: -1 37 | mipBias: -100 38 | wrapU: 1 39 | wrapV: 1 40 | wrapW: 1 41 | nPOTScale: 0 42 | lightmap: 0 43 | compressionQuality: 50 44 | spriteMode: 1 45 | spriteExtrude: 1 46 | spriteMeshType: 1 47 | alignment: 0 48 | spritePivot: {x: 0.5, y: 0.5} 49 | spritePixelsToUnits: 100 50 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 51 | spriteGenerateFallbackPhysicsShape: 1 52 | alphaUsage: 1 53 | alphaIsTransparency: 1 54 | spriteTessellationDetail: -1 55 | textureType: 8 56 | textureShape: 1 57 | singleChannelComponent: 0 58 | flipbookRows: 1 59 | flipbookColumns: 1 60 | maxTextureSizeSet: 0 61 | compressionQualitySet: 0 62 | textureFormatSet: 0 63 | ignorePngGamma: 0 64 | applyGammaDecoding: 0 65 | platformSettings: 66 | - serializedVersion: 3 67 | buildTarget: DefaultTexturePlatform 68 | maxTextureSize: 2048 69 | resizeAlgorithm: 0 70 | textureFormat: -1 71 | textureCompression: 1 72 | compressionQuality: 50 73 | crunchedCompression: 0 74 | allowsAlphaSplitting: 0 75 | overridden: 0 76 | androidETC2FallbackOverride: 0 77 | forceMaximumCompressionQuality_BC6H_BC7: 0 78 | spriteSheet: 79 | serializedVersion: 2 80 | sprites: [] 81 | outline: [] 82 | physicsShape: [] 83 | bones: [] 84 | spriteID: 5e97eb03825dee720800000000000000 85 | internalID: 0 86 | vertices: [] 87 | indices: 88 | edges: [] 89 | weights: [] 90 | secondaryTextures: [] 91 | spritePackingTag: 92 | pSDRemoveMatte: 0 93 | pSDShowRemoveMatteOption: 0 94 | userData: 95 | assetBundleName: 96 | assetBundleVariant: 97 | -------------------------------------------------------------------------------- /HelpScreenshots/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-on/UnityBuildManager/5ccccffd24b63fdfe65d45a02362e5798e941ee1/HelpScreenshots/2.png -------------------------------------------------------------------------------- /HelpScreenshots/2.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0d95ddcb067635246a02b3d6b50fe306 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | vTOnly: 0 27 | grayScaleToAlpha: 0 28 | generateCubemap: 6 29 | cubemapConvolution: 0 30 | seamlessCubemap: 0 31 | textureFormat: 1 32 | maxTextureSize: 2048 33 | textureSettings: 34 | serializedVersion: 2 35 | filterMode: -1 36 | aniso: -1 37 | mipBias: -100 38 | wrapU: 1 39 | wrapV: 1 40 | wrapW: 1 41 | nPOTScale: 0 42 | lightmap: 0 43 | compressionQuality: 50 44 | spriteMode: 1 45 | spriteExtrude: 1 46 | spriteMeshType: 1 47 | alignment: 0 48 | spritePivot: {x: 0.5, y: 0.5} 49 | spritePixelsToUnits: 100 50 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 51 | spriteGenerateFallbackPhysicsShape: 1 52 | alphaUsage: 1 53 | alphaIsTransparency: 1 54 | spriteTessellationDetail: -1 55 | textureType: 8 56 | textureShape: 1 57 | singleChannelComponent: 0 58 | flipbookRows: 1 59 | flipbookColumns: 1 60 | maxTextureSizeSet: 0 61 | compressionQualitySet: 0 62 | textureFormatSet: 0 63 | ignorePngGamma: 0 64 | applyGammaDecoding: 0 65 | platformSettings: 66 | - serializedVersion: 3 67 | buildTarget: DefaultTexturePlatform 68 | maxTextureSize: 2048 69 | resizeAlgorithm: 0 70 | textureFormat: -1 71 | textureCompression: 1 72 | compressionQuality: 50 73 | crunchedCompression: 0 74 | allowsAlphaSplitting: 0 75 | overridden: 0 76 | androidETC2FallbackOverride: 0 77 | forceMaximumCompressionQuality_BC6H_BC7: 0 78 | spriteSheet: 79 | serializedVersion: 2 80 | sprites: [] 81 | outline: [] 82 | physicsShape: [] 83 | bones: [] 84 | spriteID: 5e97eb03825dee720800000000000000 85 | internalID: 0 86 | vertices: [] 87 | indices: 88 | edges: [] 89 | weights: [] 90 | secondaryTextures: [] 91 | spritePackingTag: 92 | pSDRemoveMatte: 0 93 | pSDShowRemoveMatteOption: 0 94 | userData: 95 | assetBundleName: 96 | assetBundleVariant: 97 | -------------------------------------------------------------------------------- /HelpScreenshots/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-on/UnityBuildManager/5ccccffd24b63fdfe65d45a02362e5798e941ee1/HelpScreenshots/3.png -------------------------------------------------------------------------------- /HelpScreenshots/3.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b613db0d7312e49498cf4ca99faa8174 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | vTOnly: 0 27 | grayScaleToAlpha: 0 28 | generateCubemap: 6 29 | cubemapConvolution: 0 30 | seamlessCubemap: 0 31 | textureFormat: 1 32 | maxTextureSize: 2048 33 | textureSettings: 34 | serializedVersion: 2 35 | filterMode: -1 36 | aniso: -1 37 | mipBias: -100 38 | wrapU: 1 39 | wrapV: 1 40 | wrapW: 1 41 | nPOTScale: 0 42 | lightmap: 0 43 | compressionQuality: 50 44 | spriteMode: 1 45 | spriteExtrude: 1 46 | spriteMeshType: 1 47 | alignment: 0 48 | spritePivot: {x: 0.5, y: 0.5} 49 | spritePixelsToUnits: 100 50 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 51 | spriteGenerateFallbackPhysicsShape: 1 52 | alphaUsage: 1 53 | alphaIsTransparency: 1 54 | spriteTessellationDetail: -1 55 | textureType: 8 56 | textureShape: 1 57 | singleChannelComponent: 0 58 | flipbookRows: 1 59 | flipbookColumns: 1 60 | maxTextureSizeSet: 0 61 | compressionQualitySet: 0 62 | textureFormatSet: 0 63 | ignorePngGamma: 0 64 | applyGammaDecoding: 0 65 | platformSettings: 66 | - serializedVersion: 3 67 | buildTarget: DefaultTexturePlatform 68 | maxTextureSize: 2048 69 | resizeAlgorithm: 0 70 | textureFormat: -1 71 | textureCompression: 1 72 | compressionQuality: 50 73 | crunchedCompression: 0 74 | allowsAlphaSplitting: 0 75 | overridden: 0 76 | androidETC2FallbackOverride: 0 77 | forceMaximumCompressionQuality_BC6H_BC7: 0 78 | spriteSheet: 79 | serializedVersion: 2 80 | sprites: [] 81 | outline: [] 82 | physicsShape: [] 83 | bones: [] 84 | spriteID: 5e97eb03825dee720800000000000000 85 | internalID: 0 86 | vertices: [] 87 | indices: 88 | edges: [] 89 | weights: [] 90 | secondaryTextures: [] 91 | spritePackingTag: 92 | pSDRemoveMatte: 0 93 | pSDShowRemoveMatteOption: 0 94 | userData: 95 | assetBundleName: 96 | assetBundleVariant: 97 | -------------------------------------------------------------------------------- /HelpScreenshots/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-on/UnityBuildManager/5ccccffd24b63fdfe65d45a02362e5798e941ee1/HelpScreenshots/4.png -------------------------------------------------------------------------------- /HelpScreenshots/4.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2c8b803f9370c8b46851b72e847b7f84 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | vTOnly: 0 27 | grayScaleToAlpha: 0 28 | generateCubemap: 6 29 | cubemapConvolution: 0 30 | seamlessCubemap: 0 31 | textureFormat: 1 32 | maxTextureSize: 2048 33 | textureSettings: 34 | serializedVersion: 2 35 | filterMode: -1 36 | aniso: -1 37 | mipBias: -100 38 | wrapU: 1 39 | wrapV: 1 40 | wrapW: 1 41 | nPOTScale: 0 42 | lightmap: 0 43 | compressionQuality: 50 44 | spriteMode: 1 45 | spriteExtrude: 1 46 | spriteMeshType: 1 47 | alignment: 0 48 | spritePivot: {x: 0.5, y: 0.5} 49 | spritePixelsToUnits: 100 50 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 51 | spriteGenerateFallbackPhysicsShape: 1 52 | alphaUsage: 1 53 | alphaIsTransparency: 1 54 | spriteTessellationDetail: -1 55 | textureType: 8 56 | textureShape: 1 57 | singleChannelComponent: 0 58 | flipbookRows: 1 59 | flipbookColumns: 1 60 | maxTextureSizeSet: 0 61 | compressionQualitySet: 0 62 | textureFormatSet: 0 63 | ignorePngGamma: 0 64 | applyGammaDecoding: 0 65 | platformSettings: 66 | - serializedVersion: 3 67 | buildTarget: DefaultTexturePlatform 68 | maxTextureSize: 2048 69 | resizeAlgorithm: 0 70 | textureFormat: -1 71 | textureCompression: 1 72 | compressionQuality: 50 73 | crunchedCompression: 0 74 | allowsAlphaSplitting: 0 75 | overridden: 0 76 | androidETC2FallbackOverride: 0 77 | forceMaximumCompressionQuality_BC6H_BC7: 0 78 | spriteSheet: 79 | serializedVersion: 2 80 | sprites: [] 81 | outline: [] 82 | physicsShape: [] 83 | bones: [] 84 | spriteID: 5e97eb03825dee720800000000000000 85 | internalID: 0 86 | vertices: [] 87 | indices: 88 | edges: [] 89 | weights: [] 90 | secondaryTextures: [] 91 | spritePackingTag: 92 | pSDRemoveMatte: 0 93 | pSDShowRemoveMatteOption: 0 94 | userData: 95 | assetBundleName: 96 | assetBundleVariant: 97 | -------------------------------------------------------------------------------- /HelpScreenshots/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-on/UnityBuildManager/5ccccffd24b63fdfe65d45a02362e5798e941ee1/HelpScreenshots/5.png -------------------------------------------------------------------------------- /HelpScreenshots/5.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a2d20e29cb168394093d24227344d6d6 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | vTOnly: 0 27 | grayScaleToAlpha: 0 28 | generateCubemap: 6 29 | cubemapConvolution: 0 30 | seamlessCubemap: 0 31 | textureFormat: 1 32 | maxTextureSize: 2048 33 | textureSettings: 34 | serializedVersion: 2 35 | filterMode: -1 36 | aniso: -1 37 | mipBias: -100 38 | wrapU: 1 39 | wrapV: 1 40 | wrapW: 1 41 | nPOTScale: 0 42 | lightmap: 0 43 | compressionQuality: 50 44 | spriteMode: 1 45 | spriteExtrude: 1 46 | spriteMeshType: 1 47 | alignment: 0 48 | spritePivot: {x: 0.5, y: 0.5} 49 | spritePixelsToUnits: 100 50 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 51 | spriteGenerateFallbackPhysicsShape: 1 52 | alphaUsage: 1 53 | alphaIsTransparency: 1 54 | spriteTessellationDetail: -1 55 | textureType: 8 56 | textureShape: 1 57 | singleChannelComponent: 0 58 | flipbookRows: 1 59 | flipbookColumns: 1 60 | maxTextureSizeSet: 0 61 | compressionQualitySet: 0 62 | textureFormatSet: 0 63 | ignorePngGamma: 0 64 | applyGammaDecoding: 0 65 | platformSettings: 66 | - serializedVersion: 3 67 | buildTarget: DefaultTexturePlatform 68 | maxTextureSize: 2048 69 | resizeAlgorithm: 0 70 | textureFormat: -1 71 | textureCompression: 1 72 | compressionQuality: 50 73 | crunchedCompression: 0 74 | allowsAlphaSplitting: 0 75 | overridden: 0 76 | androidETC2FallbackOverride: 0 77 | forceMaximumCompressionQuality_BC6H_BC7: 0 78 | spriteSheet: 79 | serializedVersion: 2 80 | sprites: [] 81 | outline: [] 82 | physicsShape: [] 83 | bones: [] 84 | spriteID: 5e97eb03825dee720800000000000000 85 | internalID: 0 86 | vertices: [] 87 | indices: 88 | edges: [] 89 | weights: [] 90 | secondaryTextures: [] 91 | spritePackingTag: 92 | pSDRemoveMatte: 0 93 | pSDShowRemoveMatteOption: 0 94 | userData: 95 | assetBundleName: 96 | assetBundleVariant: 97 | -------------------------------------------------------------------------------- /HelpScreenshots/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-on/UnityBuildManager/5ccccffd24b63fdfe65d45a02362e5798e941ee1/HelpScreenshots/6.png -------------------------------------------------------------------------------- /HelpScreenshots/6.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0a68884fc1d3f8a4fb9a95a3eec09888 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | vTOnly: 0 27 | grayScaleToAlpha: 0 28 | generateCubemap: 6 29 | cubemapConvolution: 0 30 | seamlessCubemap: 0 31 | textureFormat: 1 32 | maxTextureSize: 2048 33 | textureSettings: 34 | serializedVersion: 2 35 | filterMode: -1 36 | aniso: -1 37 | mipBias: -100 38 | wrapU: 1 39 | wrapV: 1 40 | wrapW: 1 41 | nPOTScale: 0 42 | lightmap: 0 43 | compressionQuality: 50 44 | spriteMode: 1 45 | spriteExtrude: 1 46 | spriteMeshType: 1 47 | alignment: 0 48 | spritePivot: {x: 0.5, y: 0.5} 49 | spritePixelsToUnits: 100 50 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 51 | spriteGenerateFallbackPhysicsShape: 1 52 | alphaUsage: 1 53 | alphaIsTransparency: 1 54 | spriteTessellationDetail: -1 55 | textureType: 8 56 | textureShape: 1 57 | singleChannelComponent: 0 58 | flipbookRows: 1 59 | flipbookColumns: 1 60 | maxTextureSizeSet: 0 61 | compressionQualitySet: 0 62 | textureFormatSet: 0 63 | ignorePngGamma: 0 64 | applyGammaDecoding: 0 65 | platformSettings: 66 | - serializedVersion: 3 67 | buildTarget: DefaultTexturePlatform 68 | maxTextureSize: 2048 69 | resizeAlgorithm: 0 70 | textureFormat: -1 71 | textureCompression: 1 72 | compressionQuality: 50 73 | crunchedCompression: 0 74 | allowsAlphaSplitting: 0 75 | overridden: 0 76 | androidETC2FallbackOverride: 0 77 | forceMaximumCompressionQuality_BC6H_BC7: 0 78 | spriteSheet: 79 | serializedVersion: 2 80 | sprites: [] 81 | outline: [] 82 | physicsShape: [] 83 | bones: [] 84 | spriteID: 5e97eb03825dee720800000000000000 85 | internalID: 0 86 | vertices: [] 87 | indices: 88 | edges: [] 89 | weights: [] 90 | secondaryTextures: [] 91 | spritePackingTag: 92 | pSDRemoveMatte: 0 93 | pSDShowRemoveMatteOption: 0 94 | userData: 95 | assetBundleName: 96 | assetBundleVariant: 97 | -------------------------------------------------------------------------------- /HelpScreenshots/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-on/UnityBuildManager/5ccccffd24b63fdfe65d45a02362e5798e941ee1/HelpScreenshots/7.png -------------------------------------------------------------------------------- /HelpScreenshots/7.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6870276a996f5e6429b3fd9d6598a3b8 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | vTOnly: 0 27 | grayScaleToAlpha: 0 28 | generateCubemap: 6 29 | cubemapConvolution: 0 30 | seamlessCubemap: 0 31 | textureFormat: 1 32 | maxTextureSize: 2048 33 | textureSettings: 34 | serializedVersion: 2 35 | filterMode: -1 36 | aniso: -1 37 | mipBias: -100 38 | wrapU: 1 39 | wrapV: 1 40 | wrapW: 1 41 | nPOTScale: 0 42 | lightmap: 0 43 | compressionQuality: 50 44 | spriteMode: 1 45 | spriteExtrude: 1 46 | spriteMeshType: 1 47 | alignment: 0 48 | spritePivot: {x: 0.5, y: 0.5} 49 | spritePixelsToUnits: 100 50 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 51 | spriteGenerateFallbackPhysicsShape: 1 52 | alphaUsage: 1 53 | alphaIsTransparency: 1 54 | spriteTessellationDetail: -1 55 | textureType: 8 56 | textureShape: 1 57 | singleChannelComponent: 0 58 | flipbookRows: 1 59 | flipbookColumns: 1 60 | maxTextureSizeSet: 0 61 | compressionQualitySet: 0 62 | textureFormatSet: 0 63 | ignorePngGamma: 0 64 | applyGammaDecoding: 0 65 | platformSettings: 66 | - serializedVersion: 3 67 | buildTarget: DefaultTexturePlatform 68 | maxTextureSize: 2048 69 | resizeAlgorithm: 0 70 | textureFormat: -1 71 | textureCompression: 1 72 | compressionQuality: 50 73 | crunchedCompression: 0 74 | allowsAlphaSplitting: 0 75 | overridden: 0 76 | androidETC2FallbackOverride: 0 77 | forceMaximumCompressionQuality_BC6H_BC7: 0 78 | spriteSheet: 79 | serializedVersion: 2 80 | sprites: [] 81 | outline: [] 82 | physicsShape: [] 83 | bones: [] 84 | spriteID: 5e97eb03825dee720800000000000000 85 | internalID: 0 86 | vertices: [] 87 | indices: 88 | edges: [] 89 | weights: [] 90 | secondaryTextures: [] 91 | spritePackingTag: 92 | pSDRemoveMatte: 0 93 | pSDShowRemoveMatteOption: 0 94 | userData: 95 | assetBundleName: 96 | assetBundleVariant: 97 | -------------------------------------------------------------------------------- /HelpScreenshots/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-on/UnityBuildManager/5ccccffd24b63fdfe65d45a02362e5798e941ee1/HelpScreenshots/8.png -------------------------------------------------------------------------------- /HelpScreenshots/8.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 45ce2ba90a3439b43b61460971b8cf59 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | vTOnly: 0 27 | grayScaleToAlpha: 0 28 | generateCubemap: 6 29 | cubemapConvolution: 0 30 | seamlessCubemap: 0 31 | textureFormat: 1 32 | maxTextureSize: 2048 33 | textureSettings: 34 | serializedVersion: 2 35 | filterMode: -1 36 | aniso: -1 37 | mipBias: -100 38 | wrapU: 1 39 | wrapV: 1 40 | wrapW: 1 41 | nPOTScale: 0 42 | lightmap: 0 43 | compressionQuality: 50 44 | spriteMode: 1 45 | spriteExtrude: 1 46 | spriteMeshType: 1 47 | alignment: 0 48 | spritePivot: {x: 0.5, y: 0.5} 49 | spritePixelsToUnits: 100 50 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 51 | spriteGenerateFallbackPhysicsShape: 1 52 | alphaUsage: 1 53 | alphaIsTransparency: 1 54 | spriteTessellationDetail: -1 55 | textureType: 8 56 | textureShape: 1 57 | singleChannelComponent: 0 58 | flipbookRows: 1 59 | flipbookColumns: 1 60 | maxTextureSizeSet: 0 61 | compressionQualitySet: 0 62 | textureFormatSet: 0 63 | ignorePngGamma: 0 64 | applyGammaDecoding: 0 65 | platformSettings: 66 | - serializedVersion: 3 67 | buildTarget: DefaultTexturePlatform 68 | maxTextureSize: 2048 69 | resizeAlgorithm: 0 70 | textureFormat: -1 71 | textureCompression: 1 72 | compressionQuality: 50 73 | crunchedCompression: 0 74 | allowsAlphaSplitting: 0 75 | overridden: 0 76 | androidETC2FallbackOverride: 0 77 | forceMaximumCompressionQuality_BC6H_BC7: 0 78 | spriteSheet: 79 | serializedVersion: 2 80 | sprites: [] 81 | outline: [] 82 | physicsShape: [] 83 | bones: [] 84 | spriteID: 5e97eb03825dee720800000000000000 85 | internalID: 0 86 | vertices: [] 87 | indices: 88 | edges: [] 89 | weights: [] 90 | secondaryTextures: [] 91 | spritePackingTag: 92 | pSDRemoveMatte: 0 93 | pSDShowRemoveMatteOption: 0 94 | userData: 95 | assetBundleName: 96 | assetBundleVariant: 97 | -------------------------------------------------------------------------------- /HelpScreenshots/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-on/UnityBuildManager/5ccccffd24b63fdfe65d45a02362e5798e941ee1/HelpScreenshots/9.png -------------------------------------------------------------------------------- /HelpScreenshots/9.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6f67007888f2840438724c37243bfd54 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | vTOnly: 0 27 | grayScaleToAlpha: 0 28 | generateCubemap: 6 29 | cubemapConvolution: 0 30 | seamlessCubemap: 0 31 | textureFormat: 1 32 | maxTextureSize: 2048 33 | textureSettings: 34 | serializedVersion: 2 35 | filterMode: -1 36 | aniso: -1 37 | mipBias: -100 38 | wrapU: 1 39 | wrapV: 1 40 | wrapW: 1 41 | nPOTScale: 0 42 | lightmap: 0 43 | compressionQuality: 50 44 | spriteMode: 1 45 | spriteExtrude: 1 46 | spriteMeshType: 1 47 | alignment: 0 48 | spritePivot: {x: 0.5, y: 0.5} 49 | spritePixelsToUnits: 100 50 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 51 | spriteGenerateFallbackPhysicsShape: 1 52 | alphaUsage: 1 53 | alphaIsTransparency: 1 54 | spriteTessellationDetail: -1 55 | textureType: 8 56 | textureShape: 1 57 | singleChannelComponent: 0 58 | flipbookRows: 1 59 | flipbookColumns: 1 60 | maxTextureSizeSet: 0 61 | compressionQualitySet: 0 62 | textureFormatSet: 0 63 | ignorePngGamma: 0 64 | applyGammaDecoding: 0 65 | platformSettings: 66 | - serializedVersion: 3 67 | buildTarget: DefaultTexturePlatform 68 | maxTextureSize: 2048 69 | resizeAlgorithm: 0 70 | textureFormat: -1 71 | textureCompression: 1 72 | compressionQuality: 50 73 | crunchedCompression: 0 74 | allowsAlphaSplitting: 0 75 | overridden: 0 76 | androidETC2FallbackOverride: 0 77 | forceMaximumCompressionQuality_BC6H_BC7: 0 78 | spriteSheet: 79 | serializedVersion: 2 80 | sprites: [] 81 | outline: [] 82 | physicsShape: [] 83 | bones: [] 84 | spriteID: 5e97eb03825dee720800000000000000 85 | internalID: 0 86 | vertices: [] 87 | indices: 88 | edges: [] 89 | weights: [] 90 | secondaryTextures: [] 91 | spritePackingTag: 92 | pSDRemoveMatte: 0 93 | pSDShowRemoveMatteOption: 0 94 | userData: 95 | assetBundleName: 96 | assetBundleVariant: 97 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 82c145209b674a1795c349835536a854 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Build & Changelog manager 2 | 3 | ## Description 4 | Utility for running builds sequence & pushing them to itch.io and github 5 | 6 | 'Build & Changelog manager' is an asset that can: 7 | * Run multiple builds 8 | * Archivate build 9 | * Push build to itch.io 10 | * Push build to Github releases 11 | * Auto optimizes release builds for better performace and testing builds for faster build time 12 | * Maintain defines and options for each build and sequence 13 | * Keep changelog and readme files 14 | * Auto adds changelog and readme to game folders 15 | 16 | Also it nicely integrated with [Team-on Unity game template](https://github.com/Team-on/UnityGameTemplate) 17 | 18 | 19 | ## Editor window & how to use it 20 | ![Main screen](HelpScreenshots/1.png) 21 | Here are main(and only one) Build manager window. Open it in *Windows/BuildManager/Builds window* or *Alt+B*. Lets look into it step by step 22 | 23 | --------------------- 24 | 25 | ### Global data 26 | ![Global data](HelpScreenshots/2.png) 27 | First foldout is responsible for global data, that usually setuped once or before major builds. 28 | - *Company name*, *Product name*, *Version*, *Android bundle version* and *Scripting defines* is just a shortcut for *PlayerSettings* 29 | - *Itch.io link* - required data for itch.io pushing. You can press on *Docs* to get how to generate that and *Open* to open your game page 30 | - *Github token* - token with **read, write:packages and delete:packages** access. You can press on *Generate* to get how to generate that and *Docs* to look how that work 31 | - *Github user name* - github user or group name 32 | - *Github repo name* - repository name 33 | 34 | --------------------- 35 | 36 | ### Build buttons 37 | ![Build buttons](HelpScreenshots/5.png) 38 | Here are buttons that run build sequences. There are one button for each sequence. You can hide button by disabling sequence 39 | 40 | --------------------- 41 | 42 | ### Sequence general 43 | ![Sequence general](HelpScreenshots/6.png) 44 | This is sequence settings. Here you can enable/disable sequence via chech box, change it name and add/remove sequences. 45 | 46 | --------------------- 47 | 48 | ### Sequence settings 49 | ![Sequence settings](HelpScreenshots/7.png) 50 | This is global sequence data. Currently you can only add more *Scripting defines* to specific sequence. It would be added to defines written in *Global data* 51 | 52 | --------------------- 53 | 54 | ### Build settings 55 | ![Build settings](HelpScreenshots/8.png) 56 | This is build settings group. Here you can enable/disable build via chech box, change it name, select target and set build settings. 57 | For each build you can set this data: 58 | - *Passby build check mark* - Use previously builded folder and just pass that to post build processing 59 | - *Release build check mark* - Apply release optimizations for build. When unchecked - optimized for faster building 60 | - *VR build check mark* - enable VR for build 61 | - *Output root* - Output root path 62 | - *Middle path* - Output specific path. Support variables 63 | - *Dir path* - path to directory that will be *archived* and pushed to *itch.io*. Support variables 64 | - *Defines build override* - add more *Scripting defines* to specific build. It would be added to defines written in *Global data* and *Sequence settings* 65 | 66 | List of supported variables for path: 67 | - $NAME - product name with all separator replaced by '_' 68 | - $PLATFORM - platform 69 | - $VERSION - PlayerSettings.bundleVersion 70 | - $DATESHORT - [last 2 digits of year] [month] [day] 71 | - $YEARSHORT - last 2 digits of year 72 | - $DATE - [year] [month] [day] 73 | - $YEAR - year 74 | - $MONTH - month 75 | - $DAY - day 76 | - $TIME - [hour] [minute] 77 | - $EXECUTABLE - platform-specific executable. E.g. .exe for windows, .apk for android... 78 | 79 | Post build processing: 80 | - *Compress* - create .zip archive 81 | - *Push to github releases* - use data from *Global data* to push build to github releases 82 | - *Push to itch.io* - use data from *Global data* to push build to itch.io 83 | - *itch.io channel* - channel for itch.io 84 | 85 | --------------------- 86 | 87 | ### Changelog general 88 | ![Changelog general](HelpScreenshots/3.png) 89 | This is changelog foldout. You need to close it, to get access to builds window back. Here you can do 2 things. 90 | - 1) Write Readme.txt file. This file will be included to build folder for standalone platforms. 91 | - 2) Keep and update changelog. It will automatically parse and created nice looking file that ill be included to build folder for standalone platforms. 92 | 93 | --------------------- 94 | 95 | ### Changelog version 96 | ![Changelog version](HelpScreenshots/4.png) 97 | So how to keep your changelog? Press on *Add version* - add new version. 98 | For each version you can: 99 | - *Remove version* 100 | - Set version number 101 | - Set version date 102 | - Set short update name 103 | - Write description about update 104 | - *Add changelog notes*. You can select for them *Type*, *Scope*, check mark is this *community suggested* feature and add *description* 105 | - *Remove note* 106 | 107 | --------------------- 108 | 109 | ### Updating CLI 110 | ![Updating CLI](HelpScreenshots/9.png) 111 | Build manager automatically download CLI for each platform in first use, but never updates it. You can update it manually in *Windows/BuildManager/Download X* 112 | 113 | 114 | ## Installation 115 | ### (For Unity 2018.3 or later) Using OpenUPM 116 | This package is available on [OpenUPM](https://openupm.com). 117 | You can install it via [openupm-cli](https://github.com/openupm/openupm-cli). 118 | ``` 119 | openupm add com.teamon.buildmanager 120 | ``` 121 | 122 | ### (For Unity 2019.2 or later) Through Unity Package Manager 123 | * MenuItem - Window - Package Manager 124 | * Add package from git url 125 | * paste `https://github.com/Team-on/UnityBuildManager.git` 126 | 127 | ### (For Unity 2018.3 or later) Using Git 128 | Find the manifest.json file in the Packages folder of your project and add a line to `dependencies` field. 129 | `"com.teamon.buildmanager": "https://github.com/Team-on/UnityBuildManager.git"` 130 | Or, use [UpmGitExtension](https://github.com/mob-sakai/UpmGitExtension) to install and update the package. 131 | 132 | ### For Unity 2018.2 or earlier 133 | 1. Download a source code zip this page 134 | 2. Extract it 135 | 3. Import it into the following directory in your Unity project 136 | - `Packages` (It works as an embedded package. For Unity 2018.1 or later) 137 | - `Assets` (Legacy way. For Unity 2017.1 or later) 138 | 139 | ### From Unity Asset Store 140 | 1. https://assetstore.unity.com/packages/slug/188940 141 | 2. Add it to project as usual 142 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e05f7a80ff6c4765b5b1880d739ccc2d 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.teamon.buildmanager", 3 | "version": "1.1.4", 4 | "displayName": "Build Manager", 5 | "description": "Utility for running builds sequence & pushing them to markets & keeping changelog", 6 | "unity": "2019.1", 7 | "unityRelease": "0b1", 8 | "type": "tool", 9 | "keywords": [ 10 | "attribute", 11 | "project", 12 | "editor" 13 | ], 14 | "author": { 15 | "name": "Team", 16 | "email": "timonsol13@gmail.com", 17 | "url": "https://github.com/Team-on" 18 | } 19 | } -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ac737fdc351348b2bbacc0b8a187cc62 3 | PackageManifestImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | --------------------------------------------------------------------------------