Unity 6.3
0 онлайн 106 гостей 3 в системе
Вход
Строительство и публикации Шаг 15 из 25

Создание пользовательского скрипта сборки

Чтобы настроить, как 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.
  • Создание обратных вызовов: Скрипт использует BuildPlayerProcessor build обратный вызов для впрыска 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:

  1. Выберите нужный профиль сборки в окне Профили сборки.
  2. Выберите 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. Дополнительные сведения об аргументах командной строки см. в Создание проигрывателя из командной строки.

Дополнительные ресурсы