文章

Package内的Shader打包方法

Package内的Shader打包方法

Package内的Shader打包方法

00 前言

通常的打包方式是采用将工程中的资源设置好AssetBundle名称和扩展名的方式, 再使用:

public static AssetBundleManifest BuildAssetBundles (string outputPath, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform);

命令进行打包. 其中:

参数意义
outputPathAssetBundle 的输出路径。
assetBundleOptions资源包构建选项。
targetPlatform选择的目标构建平台。

AssetBundle 工作流程 - Unity 手册

image-20231020114247563

而Package中的资源无法在面板上输入AssetBundle的名称和扩展名.

01 处理方法-打包

对于Package内的资源, Unity提供了一个BuildAssetBundles方法的重载可以进行打包. 重载如下:

public static AssetBundleManifest BuildAssetBundles (string outputPath, AssetBundleBuild[] builds, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform);

相比之前的方法, 此重载多了一个AssetBundleBuild[]来记录AssetBundle的信息, 而不是依赖资源上的名称和扩展名.

关于AssetBundleBuild , 首先是一个结构体, 其包含的变量如下

变量意义
addressableNames用于加载资源的可寻址名称。
assetBundleNameAssetBundle 名称。
assetBundleVariantAssetBundle 变体。
assetNames属于给定 AssetBundle 的资源名称。

assetBundleName即AssetBundle名称部分, 也就是等价于之前我们在面板上输入的cube, assetBundleVariant即扩展名部分, assetNames即该AsstBundle包中所有资源的路径, 而addressableNames可以理解为对包中资源的重命名, 如果留空的话, 会直接使用assetNames本身.

此时采用类似下方的测试代码就可以进行打包操作了, 此时注意打包的平台是Android, 所以后续的加载需要将Unity的启动参数设置为-force-gles才可以正常使用Android的着色器.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Make
{
    [MenuItem("MyTools/Make")]
    public static void MakeAB()
    {
        var buildMap = new AssetBundleBuild[2];//声明一个AssetBundleBuild的数值用于记录AssetBundle包的信息, 此时为了测试直接声明了长度为2的数组, 实际操作的适合可以用List比较灵活, 然后转为数组即可.

        buildMap[0].assetBundleName = "mat";//第一个包打包材质球, 该包的名字
        buildMap[0].assetNames = new string[] { "Assets/Material/TreeMat.mat" };//具体包中包含的材质球路径

        buildMap[1].assetBundleName = "shader";//第二个包打包着色器, 该包的名字
        buildMap[1].assetNames = new string[] { "Packages/com.render.environment/Shaders/Tree/Tree_Lit_Release_10.shader" };//具体包中包含的着色器路径, 这里可以看出该着色器就在Package中
        
        BuildPipeline.BuildAssetBundles(Application.streamingAssetsPath, buildMap, BuildAssetBundleOptions.StrictMode, BuildTarget.Android);//打包命令.

    }
}

02 处理方法-加载

因为只是测试, 所以做了一个简单的mono脚本, 挂在场景中一个带Renderer的物体上, 通过代码加载并替换原Renderer的材质球. 这里要注意的是, 先加载着色器, 再加载材质球, 通过保证Unity的启动参数为-force-gles, 否则材质球会找不到着色器或者因为渲染API不对而报紫.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class LoadAb : MonoBehaviour
{
    void Start()
    {
        Renderer renderer = transform.GetComponent<Renderer>();

        AssetBundle shader_ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/shader");
        AssetBundle mat_ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/mat");
        Material[] mats = mat_ab.LoadAllAssets<Material>(); 
        renderer.material = mats[0];
    }


}

03 彩色石头

Unity还有一个名为Addressable的打包用的扩展. 具体用法看这篇文章.

参考网页

Unity新版AssetBundle打包API以及使用策略 - 简书 (jianshu.com)

[实力封装:Unity打包AssetBundle(一)_unity打包package-CSDN博客](https://blog.csdn.net/puss0/article/details/79681013)

实力封装:Unity打包AssetBundle(二)-CSDN博客

AssetBundle 工作流程 - Unity 手册

BuildPipeline-BuildAssetBundles - Unity 脚本 API

AssetBundleBuild - Unity 脚本 API

【精选】【游戏开发探究】Unity Addressables资源管理方式用起来太爽了,资源打包、加载、热更变得如此轻松(Addressable Asset System | 简称AA)_player content must be built before entering play -CSDN博客

本文由作者按照 CC BY 4.0 进行授权