private static void InitializeHeadless() { if (initializedHeadless) { return; } headlessRuntime = Resources.Load("HeadlessRuntime") as HeadlessRuntime; if (headlessRuntime != null) { currentProfile = headlessRuntime.profileName; #if UNITY_STANDALONE_WIN if (headlessRuntime.valueConsole && !Application.isEditor) { Windows.HeadlessConsole console = new Windows.HeadlessConsole(); console.Initialize(); console.SetTitle(Application.productName); Application.logMessageReceived += HandleLog; } #endif if (headlessRuntime.valueLimitFramerate) { Application.targetFrameRate = headlessRuntime.valueFramerate; QualitySettings.vSyncCount = 0; Debug.Log("Application target framerate set to " + headlessRuntime.valueFramerate); } } initializedHeadless = true; HeadlessCallbacks.InvokeCallbacks("HeadlessBeforeFirstSceneLoad"); }
static void OnBeforeSceneLoadRuntimeMethod() { if (IsHeadless()) { InitializeHeadless(); HeadlessCallbacks.InvokeCallbacks("HeadlessBeforeSceneLoad"); } }
// This function cleans a build up in a synchronized fashion // and is called regardless of whether the build was successful static void FinalizeBuildSync (bool restore) { if (restore) { try { RestoreBuild (); } catch (Exception e) { buildError = true; UnityEngine.Debug.LogError (e); } try { RevertBuild (); } catch (Exception e) { buildError = true; UnityEngine.Debug.LogError (e); } } if (buildError) { UnityEngine.Debug.LogError ("Build failed!\nHeadless Builder (v" + Headless.version + ")"); Headless.SetBuildingHeadless (false, HeadlessProfiles.currentProfile); HeadlessCallbacks.InvokeCallbacks ("HeadlessBuildFailed"); if (manualBuild || debugBuild) { SetProgress(null); } } else { UnityEngine.Debug.Log ("Build success!\nHeadless Builder (v" + Headless.version + ")"); Headless.SetBuildingHeadless(false, HeadlessProfiles.currentProfile); if (manualBuild || debugBuild) { SetProgress(null); } int finishedBuilds = EditorPrefs.GetInt ("HEADLESSBUILDER_FINISHEDBUILDS", 0); if (finishedBuilds < int.MaxValue - 64) { EditorPrefs.SetInt ("HEADLESSBUILDER_FINISHEDBUILDS", finishedBuilds + 1); } } if (queueBuild) { if (!buildError) { ManualBuildQueue (queueID + 1); } } }
static void OnAfterSceneLoadRuntimeMethod() { if (IsHeadless()) { if (headlessRuntime.valueCamera) { GameObject headlessObject = GameObject.Find("HeadlessBehaviour"); if (headlessObject == null) { headlessObject = (GameObject)GameObject.Instantiate(Resources.Load("HeadlessBehaviour")); } HeadlessBehaviour headlessBehaviour = headlessObject.GetComponent <HeadlessBehaviour> (); if (headlessBehaviour == null) { headlessBehaviour = headlessObject.AddComponent <HeadlessBehaviour> (); } Camera.onPreCull += headlessBehaviour.GetComponent <HeadlessBehaviour> ().NullifyCamera; } HeadlessCallbacks.InvokeCallbacks("HeadlessAfterSceneLoad"); } }
public static void Postprocess (string path) { SetProgress ("POSTPROCESS"); if (cloudBuild) { // If this is a cloud build, rename files and folders var subDirs = Directory.GetDirectories (path); foreach (var subDir in subDirs) { // For Windows and Linux: if (subDir.EndsWith ("_Data")) { String oldName = NormalizePath (subDir).Replace (NormalizePath (path), ""); oldName = oldName.Substring (1, oldName.IndexOf ("_data") - 1); if (!oldName.Equals (buildName)) { if (File.Exists (path + "/" + oldName + buildExtension)) { File.Move (path + "/" + oldName + buildExtension, path + "/" + buildExecutable); Directory.Move (subDir, path + "/" + buildName + "_Data"); } } } // For OSX: if (subDir.EndsWith (".app")) { String oldName = NormalizePath (subDir).Replace (NormalizePath (path), ""); oldName = oldName.Substring (1, oldName.IndexOf (".app") - 1); if (!oldName.Equals (buildName)) { if (File.Exists (subDir + "/Contents/MacOS/" + oldName)) { File.Move (subDir + "/Contents/MacOS/" + oldName, subDir + "/Contents/MacOS/" + buildExecutable); Directory.Move (subDir, path + "/" + buildName + ".app"); } } } } } if (!debugBuild) { string oldBuildExecutable = buildExecutable; if (headlessSettings.valuePlatform == HeadlessEditor.WINDOWS) { // For Windows builds, rename the executable to prevent direct execution if (File.Exists(path + "/" + buildExecutable)) { string newBuildExecutable = buildName + ".bin"; if (File.Exists(path + "/" + newBuildExecutable)) { File.Delete(path + "/" + newBuildExecutable); } File.Move(path + "/" + buildExecutable, path + "/" + newBuildExecutable); StreamWriter binaryWriter = new StreamWriter(path + "/" + buildExecutable, false); binaryWriter.Write("MZ"); binaryWriter.Close(); buildExecutable = newBuildExecutable; } } string consoleSuffix = ""; if (headlessSettings.valueConsole) { consoleSuffix = " -logFile"; } // Create readme file String nl = ""; if (headlessSettings.valuePlatform == HeadlessEditor.WINDOWS) { nl = "\r\n"; } else { nl = "\n"; } StreamWriter readmeWriter = new StreamWriter(path + "/" + "Readme_" + headlessSettings.profileName + ".txt", false); readmeWriter.Write("This build only supports headless mode." + nl); if (headlessSettings.valuePlatform != HeadlessEditor.LINUX) { readmeWriter.Write("Do not run " + oldBuildExecutable + " directly." + nl); } readmeWriter.Write("" + nl); readmeWriter.Write("INSTRUCTIONS" + nl); readmeWriter.Write("To start " + PlayerSettings.productName + " in headless mode, run:" + nl); if (headlessSettings.valuePlatform == HeadlessEditor.WINDOWS) { readmeWriter.Write("\t" + packageName + ".bat" + nl); } else if (headlessSettings.valuePlatform == HeadlessEditor.OSX) { readmeWriter.Write("\t" + "sh " + packageName + ".sh" + nl); } else if (headlessSettings.valuePlatform == HeadlessEditor.LINUX) { readmeWriter.Write("\t" + "./" + packageName + ".sh" + nl); } readmeWriter.Write("or run:" + nl); if (headlessSettings.valuePlatform == HeadlessEditor.WINDOWS) { readmeWriter.Write("\t" + buildExecutable + " -batchmode -nographics" + consoleSuffix + nl); } else if (headlessSettings.valuePlatform == HeadlessEditor.OSX) { readmeWriter.Write("\t" + "./" + buildExecutable + ".app/Contents/MacOS/" + buildExecutable + " -batchmode -nographics" + consoleSuffix + nl); } else if (headlessSettings.valuePlatform == HeadlessEditor.LINUX) { readmeWriter.Write("\t" + "./" + buildExecutable + " -batchmode -nographics" + consoleSuffix + nl); } if (headlessSettings.valuePlatform == HeadlessEditor.LINUX) { readmeWriter.Write("" + nl); readmeWriter.Write("You might have to grant execute permissions first by running:" + nl); readmeWriter.Write("\t" + "sudo chmod +x " + packageName + ".sh" + nl); readmeWriter.Write("\t" + "sudo chmod +x " + buildExecutable + nl); } readmeWriter.Close(); // Create script files if (headlessSettings.valuePlatform == HeadlessEditor.WINDOWS) { StreamWriter scriptWriter = new StreamWriter(path + "/" + packageName + ".bat", false); scriptWriter.Write("@ECHO OFF\r\n"); scriptWriter.Write(buildExecutable + " -batchmode -nographics" + consoleSuffix + "\r\n"); scriptWriter.Close(); } else if (headlessSettings.valuePlatform == HeadlessEditor.OSX || headlessSettings.valuePlatform == HeadlessEditor.LINUX) { StreamWriter scriptWriter = new StreamWriter(path + "/" + packageName + ".sh", false); scriptWriter.Write("#!/bin/bash\n"); if (headlessSettings.valuePlatform == HeadlessEditor.OSX) { scriptWriter.Write("./" + buildExecutable + ".app/Contents/MacOS/" + buildExecutable + " -batchmode -nographics" + consoleSuffix + "\n"); } else if (headlessSettings.valuePlatform == HeadlessEditor.LINUX) { scriptWriter.Write("./" + buildExecutable + " -batchmode -nographics" + consoleSuffix + "\n"); } scriptWriter.Close(); /*if (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.LinuxEditor) { ProcessStartInfo procBasic = new ProcessStartInfo (); procBasic.FileName = "open"; procBasic.WorkingDirectory = path; procBasic.Arguments = "chmod +x " + packageName + ".sh"; procBasic.WindowStyle = ProcessWindowStyle.Minimized; procBasic.CreateNoWindow = true; Process.Start (procBasic); ProcessStartInfo procSudo = new ProcessStartInfo (); procSudo.FileName = "open"; procSudo.WorkingDirectory = path; procSudo.Arguments = "sudo chmod +x " + packageName + ".sh"; procSudo.WindowStyle = ProcessWindowStyle.Minimized; procSudo.CreateNoWindow = true; Process.Start (procSudo); }*/ } } if (manualBuild) { // If this is a manual build, open the target folder HeadlessExplore.Open (path); } HeadlessCallbacks.InvokeCallbacks ("HeadlessBuildSuccess"); }
// BUILD STEPS: static bool InitializeBuild () { try { HeadlessCallbacks.InvokeCallbacks ("HeadlessBuildBefore"); if (manualBuild || debugBuild) { // Hide progress window if visible HeadlessProgress.Hide(); } if (manualBuild) { // If this is a manual build, store the currently selected build target // so we can revert to that later regularTarget = EditorUserBuildSettings.activeBuildTarget; regularTargetGroup = BuildPipeline.GetBuildTargetGroup (regularTarget); } if (!batchBuild) { // Get the current build path for regular builds so we can use it as a default value try { buildPath = Directory.GetParent (EditorUserBuildSettings.GetBuildLocation (EditorUserBuildSettings.activeBuildTarget)).ToString (); } catch (Exception e) { if (e.Message.Equals ("never")) { // These errors are no problem at all, so we use this workaround to supress them UnityEngine.Debug.LogWarning (e); } } } if (manualBuild || debugBuild) { if (EditorApplication.isCompiling) { EditorUtility.DisplayDialog("Headless Builder", "You can't build while the editor is compiling.\n\n" + "Please wait for compilation to finish and try again.", "OK"); return false; } if (EditorApplication.isPlaying) { EditorUtility.DisplayDialog("Headless Builder", "You can't build while the editor is in play mode.\n\n" + "Please exit play mode by clicking the stop button and try again.", "OK"); return false; } if (headlessSettings.valueDummy && !headlessSettings.valueSkipConfirmation) { if (!EditorUtility.DisplayDialog ("Headless Builder", "You have enabled a feature that replaces your visual and audio assets with dummies.\n\n" + "This will greatly enhance your build's performance,\n" + "but will also force Unity to re-import all assets, which might take a long time.\n\n" + "Are you sure you want to continue?", "Yes", "Cancel")) { return false; } } if (headlessSettings.valueGI && UnityEditor.EditorSettings.serializationMode != UnityEditor.SerializationMode.ForceText) { if (EditorUtility.DisplayDialog ("Headless Builder", "You have enabled a feature that requires Unity's serialization mode to be set to 'Force Text',\n" + "but your current serialization mode is something else.\n\n" + "Should we change the serialization mode for you?\n" + "This might take a long time.\n\n" + "If you choose to not change the serialization mode, the relevant features will be skipped.", "Change to 'Force Text'", "Ignore")) { UnityEditor.EditorSettings.serializationMode = UnityEditor.SerializationMode.ForceText; } } // If this is a manual build, make sure the scene is saved, because we'll reload it later EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo (); for (int i = 0; i < EditorSceneManager.sceneCount; i++) { if (EditorSceneManager.GetSceneAt (i).isDirty) { UnityEngine.Debug.LogError ("Any changes to scenes must be changed before doing a headless build\nHeadless Builder (v" + Headless.version + ")"); return false; } } if (manualBuild) { // Get the build path used for previous headless builds and use it as a default, if there is any bool foundPreviousPath = false; if (headlessSettings.buildPath != null && headlessSettings.buildPath.Length > 3) { if (Directory.Exists(headlessSettings.buildPath)) { buildPath = headlessSettings.buildPath; foundPreviousPath = true; } } // Ask output folder if (!foundPreviousPath || !headlessSettings.valueRememberPath) { buildPath = EditorUtility.SaveFolderPanel("Choose Destination For Headless Build (" + headlessSettings.profileName + ")", buildPath, ""); if (buildPath.Length == 0) { UnityEngine.Debug.LogError("You must choose a destination path for the headless build\nHeadless Builder (v" + Headless.version + ")"); return false; } } } } // Set the build number headlessSettings.buildPath = buildPath; if (!debugBuild) { if (headlessSettings.buildID < int.MaxValue - 128) { headlessSettings.buildID++; } } if (manualBuild || debugBuild) { // If this is a manual build, show the progress bar window progressWindow = HeadlessProgress.Init(); } SetProgress ("INIT"); return true; } catch (Exception e) { UnityEngine.Debug.LogError (e); return false; } }