You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
261 lines
10 KiB
C#
261 lines
10 KiB
C#
2 weeks ago
|
// Shady
|
||
|
// Build Maker
|
||
|
// For making iOS and Android builds automatically at default paths outside project folder
|
||
|
// Default Path for iOS build is /Users/${UserName}/Documents/_Builds/${Product Name}/iOS Build
|
||
|
// Default Path for Android build is ${UserName}/Documents/_Builds/${Product Name}/Android Build
|
||
|
// Only active scenes in build settings are included in build
|
||
|
// No need to create any folders all folders will be created automatically
|
||
|
// If build already exists no need to delete, it will Append existing build for iOS
|
||
|
// If APK already exists with the same version it will be deleted and new build will be generated
|
||
|
// If build is completed succesfully respective folders are automatically opened
|
||
|
// Shortcut key for Generating iOS Build => Cmd + Shift + i
|
||
|
// Shortcut key opening Build Path => Cmd + Shift + o
|
||
|
|
||
|
using System;
|
||
|
using System.IO;
|
||
|
using UnityEngine;
|
||
|
using System.Collections.Generic;
|
||
|
|
||
|
#if UNITY_EDITOR
|
||
|
|
||
|
using UnityEditor;
|
||
|
using UnityEditor.Build.Reporting;
|
||
|
|
||
|
#endif
|
||
|
|
||
|
namespace Shady.Utils
|
||
|
{
|
||
|
public static class BuildMaker
|
||
|
{
|
||
|
#if UNITY_EDITOR
|
||
|
|
||
|
//===================================================
|
||
|
// FIELDS
|
||
|
//===================================================
|
||
|
private static string _version = $"{PlayerSettings.bundleVersion}";
|
||
|
|
||
|
//===================================================
|
||
|
// METHODS
|
||
|
//===================================================
|
||
|
|
||
|
/// <summary>
|
||
|
/// Method return the Build path according to the OS.
|
||
|
/// </summary>
|
||
|
/// <param name="target">The Build Target type passed.</param>
|
||
|
/// <returns>A string of the whole path</returns>
|
||
|
private static string GetBuildPath(BuildTarget target, bool server)
|
||
|
{
|
||
|
string path = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
|
||
|
|
||
|
//One check only for MacOSX because on MAC the Documents folder is inside the path returned by the above statement
|
||
|
if(SystemInfo.operatingSystemFamily.Equals(OperatingSystemFamily.MacOSX))
|
||
|
path += "/Documents";
|
||
|
|
||
|
if(!Directory.Exists(path + "/_Builds"))
|
||
|
Directory.CreateDirectory(path + "/_Builds");
|
||
|
if(!Directory.Exists(path + "/_Builds/" + PlayerSettings.productName))
|
||
|
Directory.CreateDirectory(path + "/_Builds/" + PlayerSettings.productName);
|
||
|
path += "/_Builds/" + PlayerSettings.productName;
|
||
|
|
||
|
switch(target)
|
||
|
{
|
||
|
case BuildTarget.StandaloneWindows64:
|
||
|
|
||
|
if(server)
|
||
|
{
|
||
|
if(!Directory.Exists(path + "/Server Build"))
|
||
|
Directory.CreateDirectory(path + "/Server Build");
|
||
|
else
|
||
|
{
|
||
|
Directory.Delete(path + "/Server Build", true);
|
||
|
Directory.CreateDirectory(path + "/Server Build");
|
||
|
}//else end
|
||
|
|
||
|
path += "/Server Build";
|
||
|
}//if end
|
||
|
else
|
||
|
{
|
||
|
if(!Directory.Exists(path + "/Standalone Build"))
|
||
|
Directory.CreateDirectory(path + "/Standalone Build");
|
||
|
else
|
||
|
{
|
||
|
Directory.Delete(path + "/Standalone Build", true);
|
||
|
Directory.CreateDirectory(path + "/Standalone Build");
|
||
|
}//else end
|
||
|
|
||
|
path += "/Standalone Build";
|
||
|
}//else end
|
||
|
break;
|
||
|
case BuildTarget.Android:
|
||
|
if(!Directory.Exists(path + "/Android Build"))
|
||
|
Directory.CreateDirectory(path + "/Android Build");
|
||
|
path += "/Android Build";
|
||
|
break;
|
||
|
}//switch end
|
||
|
return path;
|
||
|
}//GetBuildPath() end
|
||
|
|
||
|
/// <summary>
|
||
|
/// Method finds and returns the active scenes in build settings.
|
||
|
/// </summary>
|
||
|
/// <returns>Return an array of the currently active scenes.</returns>
|
||
|
private static string[] GetActiveScenes()
|
||
|
{
|
||
|
List<string> scenes = new();
|
||
|
|
||
|
foreach(EditorBuildSettingsScene scene in EditorBuildSettings.scenes)
|
||
|
{
|
||
|
if(scene.enabled)
|
||
|
scenes.Add(scene.path);
|
||
|
}//loop end
|
||
|
return scenes.ToArray();
|
||
|
}//GetBuildScenes() end
|
||
|
|
||
|
/// <summary>
|
||
|
/// Method opens the OS explorer according to the path passed.
|
||
|
/// </summary>
|
||
|
/// <param name="path">The path to open.</param>
|
||
|
private static void OpenInExplorer(string path) => EditorUtility.RevealInFinder(path);
|
||
|
|
||
|
[MenuItem("Build/Generate Standalone Build")]
|
||
|
private static void GenerateStandaloneBuild()
|
||
|
{
|
||
|
if(EditorUtility.DisplayDialog("BUILD MAKER", "Do you want to Generate Standalone Build?.", "Yes", "No"))
|
||
|
MakeStandaloneBuild();
|
||
|
}//GenerateAndroidBuild() end
|
||
|
|
||
|
private static void MakeStandaloneBuild()
|
||
|
{
|
||
|
string path = GetBuildPath(BuildTarget.StandaloneWindows64, false);
|
||
|
string name = path + $"/{PlayerSettings.productName}.exe";
|
||
|
|
||
|
BuildPlayerOptions buildPlayerOptions = new()
|
||
|
{
|
||
|
scenes = GetActiveScenes(),
|
||
|
locationPathName = name,
|
||
|
target = BuildTarget.StandaloneWindows64,
|
||
|
subtarget = (int)StandaloneBuildSubtarget.Player,
|
||
|
options = BuildOptions.None
|
||
|
};
|
||
|
|
||
|
BuildReport report = BuildPipeline.BuildPlayer(buildPlayerOptions);
|
||
|
BuildSummary summary = report.summary;
|
||
|
|
||
|
if(summary.result == BuildResult.Succeeded)
|
||
|
{
|
||
|
OpenInExplorer(path);
|
||
|
Debug.Log("Standalone Build Generated Successfully to path\n" + path);
|
||
|
}//if end
|
||
|
}//MakeStandaloneBuild() end
|
||
|
|
||
|
[MenuItem("Build/Generate Server Build %#s")]
|
||
|
private static void GenerateServerBuild()
|
||
|
{
|
||
|
if(EditorUtility.DisplayDialog("BUILD MAKER", "Do you want to Generate Server Build?.", "Yes", "No"))
|
||
|
MakeServerBuild();
|
||
|
}//GenerateAndroidBuild() end
|
||
|
|
||
|
private static void MakeServerBuild()
|
||
|
{
|
||
|
string path = GetBuildPath(BuildTarget.StandaloneWindows64, true);
|
||
|
string name = path + $"/{PlayerSettings.productName}.exe";
|
||
|
|
||
|
BuildPlayerOptions buildPlayerOptions = new()
|
||
|
{
|
||
|
scenes = GetActiveScenes(),
|
||
|
locationPathName = name,
|
||
|
target = BuildTarget.StandaloneWindows64,
|
||
|
subtarget = (int)StandaloneBuildSubtarget.Server,
|
||
|
options = BuildOptions.None
|
||
|
};
|
||
|
|
||
|
BuildReport report = BuildPipeline.BuildPlayer(buildPlayerOptions);
|
||
|
BuildSummary summary = report.summary;
|
||
|
|
||
|
if(summary.result == BuildResult.Succeeded)
|
||
|
{
|
||
|
CreateLaunchFile(path);
|
||
|
Debug.Log("Server Build Generated Successfully to path\n" + path);
|
||
|
// MakeAndroidBuild();
|
||
|
}//if end
|
||
|
}//MakeAndroidBuild() end
|
||
|
|
||
|
private static void CreateLaunchFile(string path)
|
||
|
{
|
||
|
path += "/Launch.bat";
|
||
|
string dq = "\"";
|
||
|
string bs = @"\";
|
||
|
string command = $"start cmd /k {dq}.{bs}{PlayerSettings.productName}.exe -batchmode -nographics -logFile output.log{dq}";
|
||
|
|
||
|
if (!File.Exists(path))
|
||
|
File.WriteAllText(path, command);
|
||
|
|
||
|
OpenInExplorer(path);
|
||
|
EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Android, BuildTarget.Android);
|
||
|
}//CreateLaunchFile() end
|
||
|
|
||
|
[MenuItem("Build/Generate Android Build %#a")]
|
||
|
private static void GenerateAndroidBuild()
|
||
|
{
|
||
|
if(EditorUtility.DisplayDialog("BUILD MAKER", "Do you want to Generate Android Build?.", "Yes", "No"))
|
||
|
MakeAndroidBuild();
|
||
|
}//GenerateAndroidBuild() end
|
||
|
|
||
|
/// <summary>
|
||
|
/// Method Generates an Android Platform Build.
|
||
|
/// </summary>
|
||
|
private static void MakeAndroidBuild()
|
||
|
{
|
||
|
string BuildPath = GetBuildPath(BuildTarget.Android, false);
|
||
|
string BuildName = BuildPath + "/" + PlayerSettings.productName + " v" + _version + ".apk";
|
||
|
|
||
|
//if same version apk exists then delete it
|
||
|
if(File.Exists(BuildName))
|
||
|
File.Delete(BuildName);
|
||
|
|
||
|
BuildPlayerOptions buildPlayerOptions = new()
|
||
|
{
|
||
|
scenes = GetActiveScenes(),
|
||
|
locationPathName = BuildName,
|
||
|
target = BuildTarget.Android,
|
||
|
options = BuildOptions.None
|
||
|
};
|
||
|
|
||
|
BuildReport report = BuildPipeline.BuildPlayer(buildPlayerOptions);
|
||
|
BuildSummary summary = report.summary;
|
||
|
|
||
|
if(summary.result == BuildResult.Succeeded)
|
||
|
{
|
||
|
OpenInExplorer(BuildName);
|
||
|
Debug.Log("Build Generated Successfully for Android Platform to path\n" + BuildPath);
|
||
|
|
||
|
}//if end
|
||
|
}//MakeAndroidBuild() end
|
||
|
|
||
|
/// <summary>
|
||
|
/// Method open the path at which the build has been generated.
|
||
|
/// </summary>
|
||
|
[MenuItem("Build/Open Build Path %#o")]
|
||
|
private static void OpenBuildPath()
|
||
|
{
|
||
|
string BuildPath = string.Empty;
|
||
|
switch(EditorUserBuildSettings.activeBuildTarget)
|
||
|
{
|
||
|
case BuildTarget.Android:
|
||
|
BuildPath = GetBuildPath(BuildTarget.Android, false);
|
||
|
|
||
|
if(File.Exists(BuildPath + "/" + PlayerSettings.productName + " v" + _version+ ".apk"))
|
||
|
{
|
||
|
OpenInExplorer(BuildPath + "/" + PlayerSettings.productName + " v" + _version + ".apk");
|
||
|
return;
|
||
|
}//if end
|
||
|
break;
|
||
|
}//switch end
|
||
|
OpenInExplorer(BuildPath);
|
||
|
}//OpenBuildPath() end
|
||
|
|
||
|
#endif
|
||
|
|
||
|
}//class end
|
||
|
|
||
|
}//namespace end
|