Создание пользовательского скрипта сборки
Чтобы настроить, как Unity создает сборку, используйте BuildPipeline для выполнения сборки, а также любых шагов до и после сборки, необходимых для вашего проекта.
Запуск сборки Player из Окно «Создание профилей» Необходимо предоставить способ вызова вашего скрипта. Наиболее распространенный способ вызова скрипта сборки – это с помощью командная строка, но вы также можете выставить свой скрипт в качестве пункта меню или вызвать его из пользовательского Unity Editor окно.
В следующих примерах используется BuildPipeline.BuildPlayer API для выполнения сборки Player. Чтобы использовать скрипты, поместите их в Editor папка проекта, или создать Актив сборки редактора.
Создание базового скрипта сборки с пунктом меню
Этот пример демонстрирует простой пользовательский скрипт сборки, который создает проигрыватель Windows, копирует файл README в папку сборки и автоматически запускает созданный проигрыватель.
Он использует MenuItem атрибут для добавления Строить > Строить Windows Игрок с Readme пункт меню к Unity Editor, что позволяет вам начать сборку из Редактора.
using System.IO;
using UnityEditor.Build.Reporting;
using UnityEditor;
using UnityEngine;
public class CustomBuild
{
[MenuItem("Build/Build Windows Player With Readme")]
public static void BuildWindowsPlayer()
{
// Define build options
string path = EditorUtility.SaveFolderPanel("Choose Location of Built Game", "", "");
var buildOptions = new BuildPlayerOptions()
{
// Adjust scene list based on your project
scenes = new string[] { "Assets/Scenes/Scene1.unity", "Assets/Scenes/Scene2.unity" },
locationPathName = path + "/MyGame.exe",
target = BuildTarget.StandaloneWindows64,
options = BuildOptions.AutoRunPlayer
};
// Build the Player
var buildReport = BuildPipeline.BuildPlayer(buildOptions);
if (buildReport.summary.result != BuildResult.Succeeded)
{
Debug.Log("Build failed!\n\n" + buildReport.SummarizeErrors());
return;
}
// Post-process: Copy README file to the build folder
File.Copy("Assets/Documentation/README.txt", path + "/README.txt", true);
}
}
Этот пример имеет следующие ограничения:
- Он работает только для одной платформы.
- Список сцен закодирован непосредственно в сценарии.
- Он обходит многие параметры сборки, настроенные в окне Профиль сборки.
- Его нельзя использовать в автоматизированном конвейере сборки, поскольку он требует ввода пользователем для выбора папки выхода каждый раз, когда он запускается.
Создание скрипта сборки для нескольких платформ
В этом примере показан пользовательский скрипт сборки, поддерживающий сборку для нескольких платформ: Windows, macOS и Android. Вы можете запустить эти сборки, выбрав платформу из меню Строительство в Unity Editor или вызвав скрипт из командной строки.
using UnityEditor;
using UnityEditor.Build.Reporting;
public static class BuildScripts
{
// Helper to get all enabled scenes in Build Settings
static string[] GetEnabledScenes()
{
// Get all enabled scenes from Build Settings
var scenesInSettings = EditorBuildSettings.scenes;
var enabledScenes = new System.Collections.Generic.List<string>();
// Iterate through all scenes and add the enabled ones
for (int i = 0; i < scenesInSettings.Length; i++)
{
if (scenesInSettings[i].enabled)
enabledScenes.Add(scenesInSettings[i].path);
}
return enabledScenes.ToArray();
}
// General build method
static void BuildForTarget(BuildTarget target, string outputPath)
{
string[] scenes = GetEnabledScenes();
// Platform-specific settings
if (target == BuildTarget.Android)
{
// Basic Android PlayerSettings (optional)
PlayerSettings.applicationIdentifier = "com.company.mygame";
PlayerSettings.bundleVersion = "1.0.0";
PlayerSettings.Android.bundleVersionCode = 1;
EditorUserBuildSettings.buildAppBundle = true; // Use AAB for Play Store
}
// Build player options
BuildPlayerOptions options = new BuildPlayerOptions
{
scenes = scenes,
locationPathName = outputPath,
target = target,
options = BuildOptions.None
};
// Execute the build
BuildReport report = BuildPipeline.BuildPlayer(options);
CheckBuildResult(report, outputPath);
}
[MenuItem("Build/Windows")]
public static void BuildWindows()
{
BuildForTarget(BuildTarget.StandaloneWindows64, "Builds/Windows/MyGame.exe");
}
[MenuItem("Build/macOS")]
public static void BuildMacOS()
{
BuildForTarget(BuildTarget.StandaloneOSX, "Builds/MacOS/MyGame.app");
}
[MenuItem("Build/Android (AAB)")]
public static void BuildAndroidAAB()
{
BuildForTarget(BuildTarget.Android, "Builds/Android/MyGame.aab");
}
// Helper to validate and log the build result
static void CheckBuildResult(BuildReport report, string outputPath)
{
// Log the build summary
var summary = report.summary;
if (summary.result == BuildResult.Succeeded)
{
UnityEngine.Debug.Log("Build succeeded at: " + outputPath + " (" + summary.totalSize + " bytes)");
}
else
{
throw new System.Exception("Build failed: " + report.SummarizeErrors());
}
}
}
Вы можете вызвать этот скрипт из командная строка с помощью одной из следующих команд:
| Платформа | Команда |
|---|---|
| Windows | -executeMethod BuildScripts.BuildWindows -buildTarget StandaloneWindows64 -quit -batchmode |
| macOS | -executeMethod BuildScripts.BuildMacOS -buildTarget StandaloneOSX -quit -batchmode |
| Android | -executeMethod BuildScripts.BuildAndroidAAB -buildTarget Android -quit -batchmode |
Этот пример представляет собой улучшение по сравнению с предыдущим примером в следующих аспектах:
- Он получает список включенных сцен из
EditorBuildSettings. - Он настраивает глобальные параметры, влияющие на поведение сборки Player. В данном случае он устанавливает параметры Android для объектов
PlayerSettingsиEditorUserBuildSettings. - Он поддерживает множество платформ через один общий метод
BuildForTarget.
Однако у него есть ограничения, так как он поддерживает только три платформы, а выходные пути жестко кодированы.
Создать расширенный скрипт сборки с профилями сборки и AssetBundles
В этом примере показан пользовательский скрипт сборки, который вводит несколько продвинутых концепций:
- Использование активного профиля сборки: Этот скрипт автоматически устанавливает список сцен, флаги и настройки на основе активный профиль сборки. Перед использованием этого скрипта настройте сборки, создав и сохранив построить профили в окне Создание профилей.
- Динамические пути выхода: Скрипт использует соглашение об именовании пути выхода, основанное на имени профиля и дате, аналогично тому, что может делать базовый сервер сборки.
- Сборки AssetBundle: Скрипт выполняет сборку AssetBundle, за которой следует сборка Player.
- Сохранение типов: Скрипт предоставляет информацию о типах из сборки AssetBundle в качестве ввода в сборку Player, так что управляет удалением кода, не удаляя типы, использованные в AssetBundles.
- Создание обратных вызовов: Скрипт использует
BuildPlayerProcessorbuild обратный вызов для впрыска AssetBundle встроить вStreamingAssetsпапка сборки Player.
using UnityEngine;
using System.IO;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEditor.Build.Profile;
// Example BuildScript that supports building the current build profile.
//
//
// It builds AssetBundles and includes them in the player build.
// Each time it runs it builds into a new directory derived from the
// current build profile and timestamp.
public class BuildScript
{
public const string kBuildRootPath = "Build"; // All builds are inside this top level project folder
public const string kAssetBundleDirectory = "AssetBundles";
public const string kPlayerDirectory = "Player";
public const string kAppName = "MyGame";
public const string kTextureSourceDirectory = "Assets/Textures";
public const string kTextureSearchPattern = "*.png";
// Global variable so that RegisterContentForPlayer can find the correct AssetBundles to include in the player build
public static string gCurrentBuildRootPath = null;
[MenuItem("Build/Build Active Profile")]
public static void BuildPlayerAndBundles()
{
var profile = BuildProfile.GetActiveBuildProfile();
if (profile == null)
throw new BuildFailedException("No active build profile is set." +
"Use the Build Profiles window or the `-activeBuildProfile` cli argument");
// Use a timestamp so that each build goes to a unique output folder
var timeStamp = System.DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
gCurrentBuildRootPath = $"{kBuildRootPath}/{profile.name}/{timeStamp}";
// Build AssetBundles so that they can be shipped inside the player
var assetBundleBuildPath = BuildAssetBundles(gCurrentBuildRootPath);
// To preserve types used by the AssetBundles
var assetBundleManifestPath = assetBundleBuildPath + "/AssetBundles.manifest";
// Build the player
var playerBuildOptions = new BuildPlayerWithProfileOptions()
{
buildProfile = profile,
locationPathName = CreatePlayerOutputPath(gCurrentBuildRootPath),
assetBundleManifestPath = assetBundleManifestPath,
// These options can be adjusted as needed.
// Note: the development and compression flags come from the build profile
options = BuildOptions.CleanBuildCache | BuildOptions.StrictMode
};
// Convenient for manual testing
if (!Application.isBatchMode)
playerBuildOptions.options |= BuildOptions.AutoRunPlayer;
var report = BuildPipeline.BuildPlayer(playerBuildOptions);
gCurrentBuildRootPath = null;
if (report.summary.result != BuildResult.Succeeded)
throw new BuildFailedException("Player build failed, see Editor log for details");
Debug.Log($"Completed build to {playerBuildOptions.locationPathName}");
}
private static string BuildAssetBundles(string buildRootDirectory)
{
var assetBundlePath = buildRootDirectory + "/" + kAssetBundleDirectory;
if (!Directory.Exists(assetBundlePath))
Directory.CreateDirectory(assetBundlePath);
// For simplicity in this example, define a single AssetBundle,
// containing all the textures found inside a hard-coded directory in the project
string[] texturePaths = Directory.GetFiles(kTextureSourceDirectory, kTextureSearchPattern, SearchOption.AllDirectories);
var assetBundleContents = new AssetBundleBuild()
{
assetBundleName = "textures.bundle",
assetNames = texturePaths
};
// The target platform will be automatically set based on the active build profile
var assetBundleBuildOptions = new BuildAssetBundlesParameters()
{
outputPath = assetBundlePath,
bundleDefinitions = new AssetBundleBuild[] { assetBundleContents }
};
AssetBundleManifest manifest = BuildPipeline.BuildAssetBundles(assetBundleBuildOptions);
if (manifest == null)
throw new BuildFailedException("AssetBundle build failed, see Editor log for details");
return assetBundlePath;
}
private static string CreatePlayerOutputPath(string buildRootDirectory)
{
var playerOutputFolder = $"{buildRootDirectory}/{kPlayerDirectory}";
if (!Directory.Exists(playerOutputFolder))
Directory.CreateDirectory(playerOutputFolder);
var playerPath = $"{playerOutputFolder}/{kAppName}";
// This property will match the target in the active build profile
var target = EditorUserBuildSettings.activeBuildTarget;
// See "Build path requirements for target platforms" in the Unity Manual
if ((target == BuildTarget.StandaloneWindows64) ||
(target == BuildTarget.StandaloneWindows))
playerPath += ".exe";
else if (target == BuildTarget.StandaloneOSX)
playerPath += ".app";
else if (target == BuildTarget.StandaloneLinux64)
playerPath += ".x86_64";
else if (target == BuildTarget.Android)
playerPath += ".aab";
return playerPath;
}
}
// Put the AssetBundle build directory into the StreamingAssets folder of the player output.
// This approach keeps built content separate from the source project, avoiding clutter in "Assets/StreamingAssets".
public class RegisterContentForPlayer : BuildPlayerProcessor
{
public override void PrepareForBuild(BuildPlayerContext buildPlayerContext)
{
var currentBuildPath = BuildScript.gCurrentBuildRootPath;
if (string.IsNullOrEmpty(currentBuildPath))
// Do not do anything if we are not in a build initiated by BuildScript
return;
buildPlayerContext.AddAdditionalPathToStreamingAssets(currentBuildPath + "/" + BuildScript.kAssetBundleDirectory);
}
public override int callbackOrder => 1;
}
Использование скрипта в редакторе
Чтобы использовать этот скрипт в Unity Editor:
- Выберите нужный профиль сборки в окне Профили сборки.
- Выберите Build > Build Active Profile из меню.
Использование скрипта из командной строки
Вы также можете вызвать этот скрипт из командной строки. На Windows команда выглядит следующим образом:
.\Unity.exe -batchmode -projectPath "C:\UnityProjects\CLIBuildExample" -activeBuildProfile "Assets\Settings\Build Profiles\MyWindowsProfile.asset" -executeMethod BuildScript.BuildPlayerAndBundles -logFile C:\logs\buildlog.txt -quit
Эквивалентная команда на macOS выглядит следующим образом:
Unity -batchmode -projectPath "~/UnityProjects/CLIBuildExample" -activeBuildProfile "Assets/Settings/Build Profiles/MyWeb - Desktop - Development.asset" -executeMethod BuildScript.BuildPlayerAndBundles -logFile "~/logs/buildlog.txt" -quit
Примечание: Настройте пути в командных строках в предыдущих примерах, чтобы они соответствовали конфигурации вашего устройства и пути к вашему проекту Unity. Дополнительные сведения об аргументах командной строки см. в Создание проигрывателя из командной строки.