Unity AssetBundle批量打包、加载(场景、Prefab)完整流程

这篇具有很好参考价值的文章主要介绍了Unity AssetBundle批量打包、加载(场景、Prefab)完整流程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1、文章介绍

2、具体思路和写法

        (1)AB包的打包

        (2)AB包的加载

        (3)AB包卸载

3、结语

1、文章介绍

本篇博客主要起记录和学习作用,简单的介绍一下AB包批量的打包和加载AB包的方式,若各位同学有幸看到本篇博客,希望能够对你有所帮助。

2、具体的思路和写法

(1)AB包的打包

先介绍一下打ab包所要用到的api  BuildPipeline.BuildAssetBundle(string outputPath,AssetBundleBuild[] builds,BuildAssetBundleOptions assetBundleOptions,BuildTarget targetPlatform)

参数1:ab包输出路径  参数2:ab包信息(主要是assetBundleName=ab包名字,assetNames=资源名)   注意:assetNames一定是要Assets下的路径,不要使用windows路径,不然打包会报错!!!

    /// <summary>
    ///   <para>Build AssetBundles from a building map.</para>
    /// </summary>
    /// <param name="outputPath">Output path for the AssetBundles.</param>
    /// <param name="builds">AssetBundle building map.</param>
    /// <param name="assetBundleOptions">AssetBundle building options.</param>
    /// <param name="targetPlatform">Target build platform.</param>
    /// <returns>
    ///   <para>The manifest listing all AssetBundles included in this build.</para>
    /// </returns>
    public static AssetBundleManifest BuildAssetBundles(
      string outputPath,
      AssetBundleBuild[] builds,
      BuildAssetBundleOptions assetBundleOptions,
      BuildTarget targetPlatform)
    {
      BuildTargetGroup buildTargetGroup = BuildPipeline.GetBuildTargetGroup(targetPlatform);
      return BuildPipeline.BuildAssetBundles(outputPath, builds, assetBundleOptions, buildTargetGroup, targetPlatform);
    }

打包之前的准备工作:

        一般ToB的小项目会有一些资源迭代的需求,所以场景资源单独放到文件夹中管理,每次有新的迭代时,只对最新版本中的场景资源进行增量打包。

        UI资源同样的道理,但是小项目UI资源不需要分版本管理,除非是企业级的项目需要热更或者需要版本管理,则分版本管理。

 unity自动打ab包,C#,Unity3d,unity,游戏引擎,c#

unity自动打ab包,C#,Unity3d,unity,游戏引擎,c#

下面是具体代码:

        打包的时候需要注意的事项,打场景包一定不能压缩,否则会加载不出来要使用BuildAssetBundleOptions.None。打其他资源的时候可以选择LZ4压缩BuildAssetBundleOptions.ChunkBasedCompression。LZ4压缩是LZMA和不压缩之间的折中方案,构建的 AssetBundle 资源文件会略大于 LZMA 压缩,但是在加载资源时不需要将所有的资源都加载下来,所以速度会比 LZMA 快。建议项目中使用它。

using System;
using System.Collections.Generic;
using System.IO;
using NWH.Common.AssetInfo;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;

namespace editor.AssetBundle
{
    public class BuildAssetBundle : Editor
    {
        /// <summary>
        /// 场景资源路径
        /// </summary>
        private static string _scenePath = $"{Application.dataPath}/AssetBundle/";

        /// <summary>
        /// UI资源路径
        /// </summary>
        private static string _uiPath = $"{Application.dataPath}/AssetBundle/Resources/";

        /// <summary>
        /// 最终场景包输出目录
        /// </summary>
        public static string SceneOutPutPath = $"{Application.persistentDataPath}/assetbundle_orgin";

        /// <summary>
        /// 最终prefab包输出目录
        /// </summary>
        public static string UiOutputPath = $"{Application.persistentDataPath}/assetbundle_uiorgin";

        [MenuItem("UnityTools/打包资源")]
        public static void BuildAssetsBundle()
        {
            BuildAllScenes();
            BuildAllPrefabs();
            //刷新文件
            AssetDatabase.Refresh();
        }
        
        private static void BuildAllScenes()
        {
            var directorys = Directory.GetDirectories(_scenePath, "V*");
            var folder = directorys[directorys.Length - 1];
            
            //获取指定文件夹下所有的.unity文件
            var sceneFiles = Directory.GetFiles(folder + $"/Scenes/", $"*.unity",
                SearchOption.AllDirectories);

            for (int i = 0; i < sceneFiles.Length; i++)
            {
                //打包进度
                EditorUtility.DisplayProgressBar($"正在打包场景中...", sceneFiles[i], 1.0f);

                if (!Directory.Exists(SceneOutPutPath))
                {
                    Directory.CreateDirectory(SceneOutPutPath);
                }

                //批量打包所有的.unity文件  设置输出路径和输出windows平台
                AssetBundleBuild buildPacket = new AssetBundleBuild();
                buildPacket.assetBundleName = $"{Path.GetFileNameWithoutExtension(sceneFiles[i]).ToLower()}.unity3d";
                buildPacket.assetNames = new string[] { sceneFiles[i].Substring(sceneFiles[i].IndexOf("Assets/")) };

                var abManifest = BuildPipeline.BuildAssetBundles(
                    SceneOutPutPath,
                    new AssetBundleBuild[]{buildPacket},
                    BuildAssetBundleOptions.None,
                    BuildTarget.StandaloneWindows64
                );
            }
        
            EditorUtility.ClearProgressBar();
        }

        private static void BuildAllPrefabs()
        {
            //获取指定文件夹下所有的.prefab文件
            var uiFiles = Directory.GetFiles(_uiPath, $"*.prefab",
                SearchOption.AllDirectories);

            if (!Directory.Exists(UiOutputPath))
            {
                Directory.CreateDirectory(UiOutputPath);
            }

            List<AssetBundleBuild> buildInfoList = new List<AssetBundleBuild>();

            for (int i = 0; i < uiFiles.Length; i++)
            {
                //打包进度
                EditorUtility.DisplayProgressBar($"正在打包预设中...", uiFiles[i], 1.0f);
                
                AssetBundleBuild buildInfo = new AssetBundleBuild();
                buildInfo.assetBundleName = $"{Path.GetFileNameWithoutExtension(uiFiles[i]).ToLower()}.unity3d";
                buildInfo.assetNames = new string[] { uiFiles[i].Substring(uiFiles[i].IndexOf("Assets/")) };
                buildInfoList.Add(buildInfo);
                
                AssetBundleManifest buildManifest = BuildPipeline.BuildAssetBundles(
                    UiOutputPath, 
                    buildInfoList.ToArray(), 
                    BuildAssetBundleOptions.ChunkBasedCompression, 
                    BuildTarget.StandaloneWindows64
                    );
            }

            EditorUtility.ClearProgressBar();
        }
    }
}

 打包完成后输出的文件:

unity自动打ab包,C#,Unity3d,unity,游戏引擎,c#

unity自动打ab包,C#,Unity3d,unity,游戏引擎,c#

(2)AB包的加载

        加载场景和UI资源我使用的是同步加载,需要用到异步加载或者网络加载的同学可以去看看其他的文章介绍。      

AssetBundle.LoadFromFile 从磁盘上的文件同步加载 AssetBundle。该函数支持任意压缩类型的捆绑包。 如果是 lzma 压缩,则将数据解压缩到内存。可以从磁盘直接读取未压缩和使用块压缩的捆绑包。

与 LoadFromFileAsync 相比,该版本是同步的,将等待 AssetBundle 对象创建完毕才返回。

这是加载 AssetBundle 的最快方法。

using System.Collections;
using System.Collections.Generic;
using UnityEditor.VersionControl;
using UnityEngine;
using utils;

public class ABMgr : IMgr<ABMgr>
{
    /// <summary>
    /// 包路径
    /// </summary>
    private string packagePath;
    
    /// <summary>
    /// ab包缓存
    /// </summary>
    private Dictionary<string, AssetBundle> abCache;

    /// <summary>
    /// 主包
    /// </summary>
    private AssetBundle mainAB = null;

    /// <summary>
    /// 主包中的配置文件---->用来获取依赖包
    /// </summary>
    private AssetBundleManifest manifest = null;

    protected override void Init()
    {
        base.Init();

        abCache = new Dictionary<string, AssetBundle>();
        packagePath = $"{Application.persistentDataPath}/assetbundle_uiorgin/";
    }

    private AssetBundle LoadABPackage(string abName)
    {
        AssetBundle ab;

        if (mainAB == null)
        {
            mainAB = AssetBundle.LoadFromFile(packagePath + "assetbundle_uiorgin");
            manifest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
        }

        var dependencies = manifest.GetAllDependencies(abName);

        for (int i = 0; i < dependencies.Length; i++)
        {
            if (!abCache.ContainsKey(dependencies[i]))
            {
                ab = AssetBundle.LoadFromFile(packagePath + dependencies[i]);
                
                abCache.Add(dependencies[i], ab);
            }
        }

        if (abCache.ContainsKey(abName)) return abCache[abName];
        else
        {
            ab = AssetBundle.LoadFromFile(packagePath + abName);
            abCache.Add(abName, ab);
            return ab;
        }
    }

    public T LoadResources<T>(string abName, string resName) where T : Object
    {
        AssetBundle ab = LoadABPackage(abName);

        return ab.LoadAsset<T>(resName);
    }
}

 ab包加载单例基类:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace utils
{
    public class IMgr<T> : MonoBehaviour where T: IMgr<T>
    {
        private static T instance;

        public static T Instance
        {
            get
            {
                if (instance != null) return instance;

                instance = FindObjectOfType<T>();

                //防止脚本还未挂到物体上,找不到的异常情况,自行创建空物体挂上去
                if (instance == null)
                {
                    new GameObject("IMgrTo" +typeof(T)).AddComponent<T>();
                }
                else instance.Init(); //保证Init只执行一次

                return instance;
            }
        }

        private void Awake()
        {
            instance = this as T;
            
            Init();
        }

        protected virtual void Init()
        {
            
        }
    }
}

 下面随便写一个例子看看加载出来的效果:

unity自动打ab包,C#,Unity3d,unity,游戏引擎,c#

 

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            OnLoadScene();
        }

        if (Input.GetKeyDown(KeyCode.A))
        {
            var go = GameObject.Find("Canvas")?.gameObject;
            //加载资源
            var testui = Instantiate(ABMgr.Instance.LoadResources<GameObject>("testui.unity3d", "testui"));
            if (testui != null && go != null)
            {
                testui.transform.SetParent(go.transform);
                testui.transform.localPosition = Vector3.zero;
                testui.transform.localScale = Vector3.one;
            }
        }
    }

    private void OnLoadScene()
    {
        var ab = AssetBundle.LoadFromFile($"{Application.persistentDataPath}/assetbundle_orgin/scene1.unity3d");

        Debug.LogError(ab.name);
        SceneManager.LoadScene("scene1", LoadSceneMode.Additive);
    }
(3)AB包的卸载

        在AssetBundle的资源使用完成后,需要对其进行卸载,以释放其占用的内存空间。AssetBundle的卸载主要靠AssetBundle.Unload这个API实现。该方法需要传入一个bool类型的参数,如果传入的是true,则会卸载AssetBundle本身及从AssetBundle加载的全部资源。如果传入的是false,则会保留已经加载的资源。
在大多数情况下都推荐使用AssetBundle.Unload(true),因为如果传入false会
造成内存资源的浪费。

如果不得不使用AssetBundle.Unload(false),则只能用以下两种方式卸载单个对象:

在场景和代码中消除对不需要的对象的所有引用。完成此操作后,调用Resources.UnloadUnusedAssets。
以非附加方式加载场景。这样会销毁当前场景中的所有对象并自动调用Resources.UnloadUnusedAssets。

// 1.解除引用后调用
Resources.UnloadUnusedAssets();
// 2.上文提到的,卸载ab所加载的所有asset
ab.Unload(true);

3、结语

        这篇文章到这里就结束了,主要是记录一下自己在项目中使用到的对场景和UI打AB包用法,后续还会进行更深入的研究资源加密、解密、分类管理等等。希望这篇文章对你有帮助,喜欢的朋友点个赞吧。谢谢。文章来源地址https://www.toymoban.com/news/detail-760622.html

到了这里,关于Unity AssetBundle批量打包、加载(场景、Prefab)完整流程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Unity 从服务器加载AssetBundle资源写入本地内存,并将下载保存的AB资源从本地内存加载至场景

    AB资源打包后有一个【目录文件】AssetBundle,他保存了所有AB资源的路径与名称, 通过aLLAssetBundleURL链接路径 组拼 从【目录文件】获得的AB资源的名字,然后再协程方法内编写相关代码,从而实现从服务器加载资源的功能。详细见代码。

    2024年02月13日
    浏览(11)
  • AssetBundle动态加载Scene场景

    AssetBundle动态加载Scene场景

    加载场景有两种方法,一种是常规的 build settings 添加scene,一种是通过 AssetBundle 加载Scene。  上面是标准的异步加载场景,如果不在build settings中添加场景,直接加载scene,就会报下面的错。 因此对于需要热更新的项目,如果场景.unity资源变更了,无法在build settings中重新设置

    2024年02月11日
    浏览(12)
  • unity加载prefab预制体

    在一个项目中会有很多生成预制体的情况,就可以写一个专门生成预制体的脚本,然后把预 制体存在Resources资源文件夹 中,只用传参数,参数为要生成的预制体的路径就可以了。 下面是生成UI预制体,需要转换一下位置, 把Transform转换成RectTransform 。 注意创建的类和函数都

    2024年02月19日
    浏览(12)
  • 【Unity】AssetBundle加载与卸载

    【Unity】AssetBundle加载与卸载

    需要注意的是同一个ab包一次只能加载一个,不可以同时加载, 报错: The AssetBundle \\\'xxxxx\\\' can\\\'t be loaded because another AssetBundle with the same files is already loaded. 如果AB包已经加载过则先进行卸载: 1、卸载全部的目前没有使用的资源: Resources.UnloadUnusedAssets() 2、卸载 AssetBundle 释放其

    2024年04月25日
    浏览(9)
  • [游戏开发][Unity]Assetbundle打包篇(1)打包流程介绍

    [游戏开发][Unity]Assetbundle打包篇(1)打包流程介绍

    打包与资源加载框架目录 先捋一下打AB包的整体思路,首先,Unity4.6版本之后就使用了全新的打包接口 无论是全新打包还是增量打包都是使用这个API,所以一切的一切,都要围绕这个API开始讲起。 该API有四个参数 string outputPath AssetBundleBuild[] builds BuildAssetBundleOptions assetBundle

    2024年02月10日
    浏览(10)
  • [游戏开发][Unity]Assetbundle打包篇(2)打包资源配置篇

    [游戏开发][Unity]Assetbundle打包篇(2)打包资源配置篇

    打包与资源加载框架目录 可视化配置的方式有很多种,Json、XML、以及Unity内置的ScriptableObject序列化 配置文件里要有哪些内容呢,很显然,最重要的就是目标文件路径,其次是权重类型,权重类型有:必要打包型、被引用打包型、忽略类型。为何会有忽略类型呢,是因为我们

    2024年02月09日
    浏览(29)
  • Unity引擎打包AssetBundle后模型网格数据丢失问题

    Unity引擎打包AssetBundle后模型网格数据丢失问题

    大家好,我是阿赵。 在项目里面,有时候会遇到这样一个问题。在Unity编辑器里面编写了一个shader,在编辑器看,效果都是没有问题的。但如果把资源打包成AssetBundle后,会发现shader的表现不对了。遇到了这种问题的时候,一般人会各自的怀疑,怀疑是不是shader写得不对,导

    2024年02月07日
    浏览(14)
  • Unity 解决SpriteAtlas图集打包AssetBundle白图问题

    Unity 解决SpriteAtlas图集打包AssetBundle白图问题

    之前文档上说勾选了Include in build之后,就不需要自己增加一个Binding脚本,但是仍然会弹出警告,并且会出现白图现象 Tight Packing 勾选之后当Sprite有透明通道可能会出现错位 不推荐勾选 选项取消勾选之后打包AssetBundle会报警告 并且出现白图现象 那是因为没有进行bing  Sprite

    2024年02月11日
    浏览(62)
  • 【Unity】AssetBundle资源异步加载以及AB包卸载

    【Unity】AssetBundle资源异步加载以及AB包卸载

    以下代码是基于上一篇文章《AssetBundle资源同步加载》的代码新增了异步加载和AB包卸载功能,有兴趣的同学可以去看看我的上一篇文章。 由于异步加载需要配合协程进行功能开发,所以我对之前封装的AB包资源加载管理器进行修改,改为继承MonoBehaviour的单例模式。 主要修改

    2023年04月08日
    浏览(9)
  • Unity的AssetBundle系统来动态加载FBX模型

    在Unity中,可以使用C#脚本和Unity的AssetBundle系统来动态加载FBX模型。以下是一个简单的示例,演示如何动态加载FBX模型: 准备FBX模型 首先,准备一个或多个FBX模型,并将它们导入到Unity项目中。确保每个FBX模型都有一个独立的游戏对象,并且已经被正确地设置为“Static”或“

    2024年02月06日
    浏览(8)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包