Last active
December 8, 2023 09:50
-
-
Save WooshiiDev/6af0e615793f7563adaf36c2b8c56b9f to your computer and use it in GitHub Desktop.
Build Window for Unity, adding some flexibility into your projects! Make sure to add this to a folder named "Editor" so that Unity doesn't show errors when building your project/game
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Diagnostics; | |
using UnityEditor; | |
using UnityEngine; | |
using UnityEditorInternal; | |
using Debug = UnityEngine.Debug; | |
using System.Collections; | |
namespace BuildTools | |
{ | |
public static class BuildData | |
{ | |
internal const string PATH_PREF = "_BuildFolder"; | |
internal const string NAME_PREF = "_BuildName"; | |
internal const string VER_PREF = "_BuildVersion"; | |
//Settings | |
internal static bool HasBuildPath => EditorPrefs.HasKey(PATH_PREF); | |
internal static string BuildPath => EditorPrefs.GetString(PATH_PREF); | |
internal static string BuildName => EditorPrefs.GetString(NAME_PREF); | |
//Defaults | |
internal static string DefaultPath => Application.dataPath; | |
internal const string DEFAULT_NAME = "Build"; | |
//Methods | |
internal static void SetBuildPath(string path) => EditorPrefs.SetString(PATH_PREF, path); | |
internal static void SetBuildName(string name) => EditorPrefs.SetString(NAME_PREF, name); | |
internal static void SetUseVersioning(int value) => EditorPrefs.SetInt(VER_PREF, value); | |
internal static void ClearPrefs() | |
{ | |
EditorPrefs.DeleteKey(PATH_PREF); | |
EditorPrefs.DeleteKey(NAME_PREF); | |
EditorPrefs.DeleteKey(VER_PREF); | |
} | |
internal static string SelectBuildFolder() => EditorUtility.SaveFolderPanel("Build Folder Path", DefaultPath, DefaultPath); | |
} | |
internal class BuildToolsWindow : EditorWindow | |
{ | |
//Build settings | |
private string prefBuildFolder = ""; | |
private string prefBuildName = ""; | |
private bool addVersioning = false; | |
private static BuildPlayerOptions options = new BuildPlayerOptions() | |
{ | |
target = BuildTarget.StandaloneWindows, | |
options = BuildOptions.Development, | |
}; | |
private static readonly string[] buttonLabel = { "PC", "Mac", "Both" }; | |
// --- GUIStyles --- | |
private static GUIStyle largeBold; | |
private static GUIStyle smallBold; | |
private static GUIStyle smallLabel; | |
// --- Scene Data --- | |
private static ReorderableList list; | |
private static Vector2 scrollPosition; | |
private static Vector2 reorderableScrollPosition; | |
// --- Properties --- | |
private static bool HasKey => BuildData.HasBuildPath; | |
private void OnEnable() | |
{ | |
this.name = "Build Tools"; | |
this.minSize = new Vector2(310, this.minSize.y); | |
titleContent = new GUIContent() | |
{ | |
text = "Build Tools", | |
image = EditorGUIUtility.Load("icons/d_BuildSettings.Standalone.Small.png") as Texture2D, | |
}; | |
if (list == null) | |
{ | |
list = new ReorderableList(null, typeof(SceneAsset), true, true, true, true); | |
list.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) => | |
{ | |
SceneAsset element = (SceneAsset)list.list[index]; | |
EditorGUI.PrefixLabel(rect, new GUIContent(index.ToString())); | |
list.list[index] = EditorGUI.ObjectField( | |
new Rect(rect.x + 18, rect.y, rect.width - 18, EditorGUIUtility.singleLineHeight), | |
element, typeof(SceneAsset), false); | |
}; | |
list.drawHeaderCallback = (Rect rect) => | |
{ | |
rect.width *= 0.5f; | |
EditorGUI.LabelField(new Rect(rect.x, rect.y, rect.width / 2, rect.height), "Build Scenes"); | |
rect.x += rect.width; | |
if (GUI.Button(rect, "Save Scenes to Build")) | |
SaveToBuild(); | |
}; | |
list.onAddCallback = (ReorderableList list) => | |
{ | |
list.list.Add(null); | |
}; | |
} | |
CheckValidation(); | |
GetBuildScenes(); | |
EditorBuildSettings.sceneListChanged -= GetBuildScenes; | |
EditorBuildSettings.sceneListChanged += GetBuildScenes; | |
} | |
private void OnGUI() | |
{ | |
if (largeBold == null) | |
{ | |
largeBold = new GUIStyle(EditorStyles.label) | |
{ | |
fontStyle = FontStyle.Bold, | |
alignment = TextAnchor.MiddleCenter, | |
fontSize = 16 | |
}; | |
} | |
if (smallLabel == null) | |
{ | |
smallLabel = new GUIStyle(EditorStyles.label) | |
{ | |
alignment = TextAnchor.MiddleCenter, | |
}; | |
} | |
if (smallBold == null) | |
{ | |
smallBold = new GUIStyle(smallLabel) | |
{ | |
fontStyle = FontStyle.Bold | |
}; | |
} | |
if (!HasKey) | |
SetupInitial(); | |
else | |
{ | |
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition); | |
DrawBuildSettings(); | |
EditorGUILayout.EndScrollView(); | |
} | |
} | |
#region Initalization | |
private void CheckValidation() | |
{ | |
if (HasKey) | |
{ | |
prefBuildFolder = BuildData.BuildPath; | |
prefBuildName = BuildData.BuildName; | |
} | |
else | |
{ | |
prefBuildFolder = BuildData.DefaultPath; | |
prefBuildName = BuildData.DEFAULT_NAME; | |
BuildData.SetBuildName(prefBuildName); | |
} | |
} | |
private void SetupInitial() | |
{ | |
GUILayout.FlexibleSpace(); | |
{ | |
EditorGUILayout.BeginHorizontal(); | |
{ | |
GUILayout.Space(10); | |
EditorGUILayout.BeginVertical(GUI.skin.window); | |
InitFolderSelection(); | |
EditorGUILayout.EndVertical(); | |
GUILayout.Space(10); | |
} | |
EditorGUILayout.EndHorizontal(); | |
} | |
GUILayout.FlexibleSpace(); | |
} | |
private void InitFolderSelection() | |
{ | |
//Base info | |
DirectorySettings(); | |
GUILayout.Label("Please choose a default folder for creating builds", smallLabel); | |
} | |
#endregion | |
#region Draw | |
private void DrawBuildSettings() | |
{ | |
DirectorySettings(); | |
BuildParameters(); | |
SceneSelector(); | |
CreateBuild(); | |
} | |
private void DirectorySettings() | |
{ | |
GUILayout.Label("Build Platform", largeBold); | |
EditorGUILayout.LabelField("Build Folder", EditorStyles.boldLabel); | |
EditorGUILayout.BeginHorizontal(); | |
{ | |
prefBuildFolder = EditorGUILayout.DelayedTextField(prefBuildFolder); | |
if (GUILayout.Button("Browse...", GUILayout.MaxWidth(80f))) | |
prefBuildFolder = BuildData.SelectBuildFolder(); | |
} | |
EditorGUILayout.EndHorizontal(); | |
EditorGUILayout.LabelField("Build File Name", EditorStyles.boldLabel); | |
//Draw build path | |
EditorGUILayout.BeginHorizontal(); | |
{ | |
prefBuildName = EditorGUILayout.DelayedTextField(prefBuildName); | |
EditorGUI.BeginDisabledGroup(true); | |
EditorGUILayout.TextField(".exe", GUILayout.MaxWidth(32f)); | |
EditorGUI.EndDisabledGroup(); | |
} | |
EditorGUILayout.EndHorizontal(); | |
EditorGUILayout.BeginHorizontal(); | |
{ | |
addVersioning = GUILayout.Toggle(addVersioning, "Add Version to Name"); | |
if (GUILayout.Button("Save Settings")) | |
{ | |
BuildData.SetBuildName(prefBuildName); | |
BuildData.SetUseVersioning(addVersioning ? 1 : 0); | |
if (!Directory.Exists(prefBuildFolder)) | |
prefBuildFolder = BuildData.DefaultPath; | |
else | |
BuildData.SetBuildPath(prefBuildFolder); | |
} | |
} | |
EditorGUILayout.EndHorizontal(); | |
} | |
private void BuildParameters() | |
{ | |
GUILayout.Space(16); | |
GUILayout.Label("Build Player Options", largeBold); | |
options.target = (BuildTarget)EditorGUILayout.EnumPopup("Target Platform", options.target); | |
options.options = (BuildOptions)EditorGUILayout.EnumPopup("Build Options", options.options); | |
} | |
//Scene | |
private void SceneSelector() | |
{ | |
GUILayout.Space(16); | |
GUILayout.Label("Scene Selector", largeBold); | |
GUILayout.BeginHorizontal(); | |
if (GUILayout.Button("Load all project scenes")) | |
GetAllScenes(); | |
if (GUILayout.Button("Load Build Scenes")) | |
GetBuildScenes(); | |
GUILayout.EndHorizontal(); | |
GUILayout.BeginHorizontal(); | |
if (GUILayout.Button("Remove null scenes")) | |
{ | |
var scenes = new List<SceneAsset>(); | |
for (int i = 0; i < list.list.Count; i++) | |
{ | |
if (list.list[i] != null) | |
scenes.Add((SceneAsset)list.list[i]); | |
} | |
list.list = scenes; | |
} | |
if (GUILayout.Button("Clear all scenes")) | |
list.list.Clear(); | |
GUILayout.EndHorizontal(); | |
list.DoLayoutList(); | |
} | |
private void CreateBuild() | |
{ | |
if (GUILayout.Button("Create Build", GUILayout.MinHeight(50))) | |
{ | |
var scenes = GetScenePaths(); | |
string build = prefBuildName; | |
if (addVersioning) | |
build += Application.version; | |
try | |
{ | |
options.scenes = scenes; | |
options.locationPathName = prefBuildFolder + "/" + build + ".exe"; | |
var player = BuildPipeline.BuildPlayer(options); | |
var summary = player.summary; | |
if (summary.result == UnityEditor.Build.Reporting.BuildResult.Succeeded) | |
{ | |
Debug.Log($"Build created successfully to {summary.outputPath} in {summary.totalTime}"); | |
if (EditorUtility.DisplayDialogComplex("Build Completed!", "Run Build?", "Yes", "No", "") == 0) | |
Process.Start(player.summary.outputPath); | |
} | |
} | |
catch (Exception e) | |
{ | |
Debug.Log(e); | |
} | |
} | |
} | |
#endregion | |
#region Helpers | |
private void GetBuildScenes() | |
{ | |
List<SceneAsset> scenes = new List<SceneAsset>(); | |
foreach (var scene in EditorBuildSettings.scenes) | |
{ | |
var asset = AssetDatabase.LoadAssetAtPath<SceneAsset>(scene.path); | |
if (asset != null) | |
{ | |
if (!scenes.Contains(asset)) | |
scenes.Add(asset); | |
} | |
} | |
list.list = scenes; | |
} | |
private void GetAllScenes() | |
{ | |
List<SceneAsset> scenes = new List<SceneAsset>(); | |
string[] allScenes = AssetDatabase.FindAssets("t:SceneAsset"); | |
foreach (var scene in allScenes) | |
{ | |
var asset = AssetDatabase.LoadAssetAtPath<SceneAsset>(AssetDatabase.GUIDToAssetPath(scene)); | |
if (asset != null) | |
{ | |
if (!scenes.Contains(asset)) | |
scenes.Add(asset); | |
} | |
} | |
list.list = scenes; | |
} | |
private void SaveToBuild() | |
{ | |
// Find valid Scene paths and make a list of EditorBuildSettingsScene | |
List<EditorBuildSettingsScene> editorBuildSettingsScenes = new List<EditorBuildSettingsScene>(); | |
IList sceneList = list.list; | |
for (int i = 0; i < sceneList.Count; i++) | |
{ | |
var scene = sceneList[i]; | |
if (scene == null) | |
{ | |
list.list.Remove(scene); | |
Debug.LogError("Removed null scene at index " + i); | |
continue; | |
} | |
SceneAsset sceneAsset = (SceneAsset)scene; | |
string scenePath = AssetDatabase.GetAssetPath(sceneAsset); | |
if (!string.IsNullOrEmpty(scenePath)) | |
editorBuildSettingsScenes.Add(new EditorBuildSettingsScene(scenePath, true)); | |
} | |
// Set the Build Settings window Scene list | |
EditorBuildSettings.scenes = editorBuildSettingsScenes.ToArray(); | |
} | |
private string[] GetScenePaths() | |
{ | |
string[] scenes = new string[EditorBuildSettings.scenes.Length]; | |
for (int i = 0; i < scenes.Length; i++) | |
scenes[i] = EditorBuildSettings.scenes[i].path; | |
return scenes; | |
} | |
#endregion | |
#region Menu Items | |
[MenuItem("Build Tools/Build Window")] | |
public static void ShowWindow() | |
{ | |
GetWindow(typeof(BuildToolsWindow)); | |
} | |
[MenuItem("Build Tools/Default Window")] | |
public static void ShowDefaultWindow() | |
{ | |
BuildPlayerWindow.ShowBuildPlayerWindow(); | |
} | |
[MenuItem("Build Tools/Clear Build Data")] | |
public static void ClearPrefData() | |
{ | |
BuildData.ClearPrefs(); | |
} | |
#endregion | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment