ue3dUnity使用Scriptable Build Pipeline构建流介绍

Unity使用Scriptable Build Pipeline构建流介绍

分类:
ue3d - Unity使用Scriptable Build Pipeline构建流介绍

这篇文章简要介绍了如何使用Unity的Scriptable Build Pipeline(SBP)建立构建流程。

什么是Scriptable Build Pipeline?

使用Scriptable Build Pipeline(可编写脚本的构建管道),可以自由构建构建流,比如资产包。

可以自定义构建AssetBundle之间的依赖关系以及输出描述依赖关系的文件的过程。

Unity还预定义了一个使用它的默认构建管道,可寻址资产系统使用它,与传统的不可定制的流水线相比,似乎性能有所提高,增量构建也有所改进。

PS:Scriptable Build Pipeline只适用于Unity 2018.3或更高版本。

安装SBP

从包管理器安装Scriptable Build Pipeline。

ue3d - Unity使用Scriptable Build Pipeline构建流介绍

了解IBuildTask

现在看看如何使用Scriptable Build Pipeline。

首先,IBuildTask需要了解界面,构建一个AssetBundle可以分为几个阶段,例如:

  1. 更改平台(iOS、Android等)
  2. 收集资产之间的依赖关系
  3. 根据依赖信息构建 AssetBundle

在Scriptable Build Pipeline中,创建了一个实现每个阶段的IBuildTask类,然后,传递的列表如下所示,以运行每个阶段。

using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEditor.Build.Pipeline.Interfaces;
using UnityEditor.Build.Pipeline;

public static class Example
{
    [MenuItem("Example/Build")]
    private static void Build()
    {
        // 按执行顺序创建和注册 IBuildTasks
        var tasks = new List<IBuildTask>
        {
            new LogPlatform()
        };
        
        // (This will be explained in the next section)
        var contexts = new BuildContext();

        // run IBuildTask 
        var returnCode = BuildTasksRunner.Run(tasks, contexts);
        
        Debug.Log(returnCode);
    }
}

// 一个只输出当前平台的 BuildTask
public class LogPlatform : IBuildTask
{
    public int Version => 1;

    public ReturnCode Run()
    {
        Debug.Log(EditorUserBuildSettings.activeBuildTarget);
        return ReturnCode.Success;
    }
}

可以看到运行它会记录当前平台。

ue3d - Unity使用Scriptable Build Pipeline构建流介绍

了解IContextObject

接下来,IBuildTask考虑像上一节那样传递参数。

在这种情况下,使用Scriptable Build Pipeline提供的DI机制。

具体如下,IContextObject将参数保存在执行的类中,IBuildTask进行DI。

using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEditor.Build.Pipeline.Interfaces;
using UnityEditor.Build.Pipeline;
using UnityEditor.Build.Pipeline.Injector;

public static class Example
{
    [MenuItem("Example/Build")]
    private static void Build()
    {
        var tasks = new List<IBuildTask>
        {
            // 切换平台
            new SwitchPlatform(),
            // 记录当前平台
            new LogPlatform()
        };
        
        var contexts = new BuildContext();
        // 为 SwitchPlatform 添加上下文
        var switchPlatformContext = new SwitchPlatformContext(BuildTargetGroup.Android, BuildTarget.Android);
        contexts.SetContextObject(switchPlatformContext);

        var returnCode = BuildTasksRunner.Run(tasks, contexts);
        
        Debug.Log(returnCode);
    }
}

public class LogPlatform : IBuildTask
{
    public int Version => 1;

    public ReturnCode Run()
    {
        Debug.Log(EditorUserBuildSettings.activeBuildTarget);
        return ReturnCode.Success;
    }
}

// BuildTask 切换平台
public class SwitchPlatform : IBuildTask
{
    // 将 InjectContext 添加到 DI 目标字段
    // 如果 DI 是任意的,则将第二个参数设置为 true
    [InjectContext(ContextUsage.In)]
    private readonly ISwitchPlatformContext _context = null;

    public int Version => 1;

    public ReturnCode Run()
    {
        return EditorUserBuildSettings.SwitchActiveBuildTarget(_context.Group, _context.Target)
            ? ReturnCode.Success
            : ReturnCode.Error;
    }
}

// SwitchPlatform 上下文接口
public interface ISwitchPlatformContext : IContextObject
{
    BuildTargetGroup Group { get; }
    BuildTarget Target { get; }
}

// SwitchPlatform 的上下文实现类
public class SwitchPlatformContext : ISwitchPlatformContext
{
    public BuildTargetGroup Group { get; }
    public BuildTarget Target { get; }
    
    public SwitchPlatformContext(BuildTargetGroup group, BuildTarget target)
    {
        Group = group;
        Target = target;
    }
}

如果运行它,可以确认日志输出是在平台切换过程运行后执行的。

ue3d - Unity使用Scriptable Build Pipeline构建流介绍

查看实际使用IBuildTask的地方

到目前为止已经了解了,IBuildTask看一下实际制作的部分。BuildTask是围绕Addressables中的UnityEditor.Build.Pipeline创建的。

如果只提取创建资产包的BuildTask的部分,它看起来如下所示。

static IList<IBuildTask> AssetBundleCompatible()
{
    var buildTasks = new List<IBuildTask>();

    // 设置
    buildTasks.Add(new SwitchToBuildPlatform());
    buildTasks.Add(new RebuildSpriteAtlasCache());

    // 玩家脚本
    buildTasks.Add(new BuildPlayerScripts());
    buildTasks.Add(new PostScriptsCallback());

    // 依赖性
    buildTasks.Add(new CalculateSceneDependencyData());
#if UNITY_2019_3_OR_NEWER
    buildTasks.Add(new CalculateCustomDependencyData());
#endif
    buildTasks.Add(new CalculateAssetDependencyData());
    buildTasks.Add(new StripUnusedSpriteSources());
    buildTasks.Add(new PostDependencyCallback());

    // 包装
    buildTasks.Add(new GenerateBundlePacking());
    buildTasks.Add(new GenerateBundleCommands());
    buildTasks.Add(new GenerateSubAssetPathMaps());
    buildTasks.Add(new GenerateBundleMaps());
    buildTasks.Add(new PostPackingCallback());

    // 写作
    buildTasks.Add(new WriteSerializedFiles());
    buildTasks.Add(new ArchiveAndCompressBundles());
    buildTasks.Add(new AppendBundleHash());
    buildTasks.Add(new PostWritingCallback());

    // 生成清单文件
    // TODO:IMPL 清单生成

    return buildTasks;
}

可以看到按照执行顺序注册了大量的BuildTasks,为了自己创建构建流程,必须在此处创建流程。

查看实际使用IContextObject的位置

接下来,看看IContextObject实际用在什么地方。

寻找它的好地方是UnityEditor.Build.Pipeline周围,此方法的摘录如下所示:

buildContext = new BuildContext(contextObjects);
buildContext.SetContextObject(parameters);
buildContext.SetContextObject(content);
buildContext.SetContextObject(result);
buildContext.SetContextObject(interfacesWrapper);
buildContext.SetContextObject(progressTracker);
buildContext.SetContextObject(buildCache);
// 如果 IDeterministicIdentifiers 与 contextObjects 一起传入,则不要添加默认值
if (!buildContext.ContainsContextObject(typeof(IDeterministicIdentifiers)))
    buildContext.SetContextObject(new Unity5PackedIdentifiers());
buildContext.SetContextObject(new BuildDependencyData());
buildContext.SetContextObject(new BundleWriteData());
buildContext.SetContextObject(BuildCallbacks);

还确认许多IContextObject已为DI注册。

仅需要定制一部分

这是关于如何使用脚本化构建管道建立构建流程的快速总结。

然而,实际上,不是从头开始建立构建流程,而是可能存在仅定制一部分就足够的情况。在这种情况下,CompatibilityBuildPipeline.BuildAssetBundles可以通过调整给定的参数来进行可选设置,如下所示。

using System.IO;
using System.Linq;
using UnityEditor;
using UnityEditor.Build.Content;
using UnityEditor.Build.Pipeline;

public class Example
{
    public static bool BuildAssetBundles(string outputPath, bool forceRebuild, bool useChunkBasedCompression,
        BuildTarget buildTarget)
    {
        // 设置选项
        var options = BuildAssetBundleOptions.None;
        if (useChunkBasedCompression)
        {
            options |= BuildAssetBundleOptions.ChunkBasedCompression;
        }
        if (forceRebuild)
        {
            options |= BuildAssetBundleOptions.ForceRebuildAssetBundle;
        }

        // 获取 AssetBundle 构建信息
        // 这不是Addressables,而是旧方法中收集AssetBundle名称的API,因此请根据需要进行更改
        var bundles = ContentBuildInterface.GenerateAssetBundleBuilds();
        // 仅将可寻址名称从完整路径更改为文件名
        for (var i = 0; i < bundles.Length; i++)
        {
            bundles[i].addressableNames = bundles[i].assetNames.Select(Path.GetFileNameWithoutExtension).ToArray();
        }

        var manifest = CompatibilityBuildPipeline.BuildAssetBundles(outputPath, bundles, options, buildTarget);
        return manifest != null;
    }
}

以上是关于Unity如何使用Scriptable Build Pipeline建立构建流程的全部内容,如果你有任何反馈,请随时在本页面下方留言。

相关信息

  • 类型:知识
  • 字数:732
  • 字符:8526
  • 适用软件:Unity
  • 说明:无
  • 编号:164286

热门内容

提示:3D天堂作为服务提供者,尊重网络版权及知识产权,对某些行为的发生不具备充分的监控能力,若无意间侵犯到您的权利,请 联系我们,我们会在收到信息后尽快给予处理。

本站文章版权归本站自创作者所有,未经允许不得转载!