Unity AssetBundle 之 (进阶)简单的自动给资源打上 AssetBundle 标签(分平台),方便 AssetBundle 打包的方法

 

 

Unity AssetBundle 之 (进阶)简单的自动给资源打上 AssetBundle 标签(分平台),方便 AssetBundle 打包的方法

 

目录

Unity AssetBundle 之 (进阶)简单的自动给资源打上 AssetBundle 标签(分平台),方便 AssetBundle 打包的方法

一、简单介绍

二、实现原理

三、注意事项

四、效果预览

五、实现步骤

六、关键脚本


 

一、简单介绍

Unity中的一些基础知识点。

本节介绍,Asset Bundle 在 Unity中的使用,进阶第一篇,如何给需要打包 Asset Bundle 的资源自动打上标签,而不是手动一个一个标签的方法,有不对的地方欢迎指正。

 

二、实现原理

1、使用 Editor 脚本,指定资源文件夹,AssetImporter 进行资源 AssetBundle 标记标签

2、标签原理,场景名称/功能文件夹名 的方式标记标签

3、使用递归,标记非文件夹,且不是.meta 的文件

4、文件类型为.unity 标签后缀为u3d,其他文件类型均标记为.ab

 

三、注意事项

1、文件夹和文件,建议同一个场景功能文件夹下尽量别有重名的文件或者文件夹(与Unity自身标签机制有些关系)

 

四、效果预览

 

五、实现步骤

1、打开Unity,新建一个空工程

 

2、把资源导进来,这里 AssetBundle 标记标签的文件夹为 AB_Resources,文件结构如下,需要标记的资源如图功能文件夹放置

 

3、新建脚本 AutoSetAssetBundleLabel ,用于给指定的文件夹资源打上AB标签,PathTools 一些 AB 路径的管理脚本

 

4、菜单栏就会有 AssetBundleTools -- Set AB Label 工具

 

5、点击Set AB Label ,就会自动给指定的文件夹资源打上AB 标签(头一次打标签可能会较慢,根据资源情况),打完之后会有一个提示

 

6、对应资源就自动打上了对应的标签

 

六、关键脚本

1、AutoSetAssetBundleLabel

/****************************************************
文件:AutoSetAssetBundleLabel.cs
作者:仙魁XAN
邮箱:https://blog.csdn.net/u014361280 
日期:2020/08/12 09:17:14
功能:Asset Bundle 簡單框架
开发思路:
    1、 定义需要打包资源的文件夹根目录
    2、遍历每个“场景”文件夹(目录)
        2.1:遍历本场景目录下所有的目录或者文件
            如果是目录,则继续“递归”访问里面的文件,直到定位到文件
        2.2:递归调用方法,找到文件,则使用 AssetImporter 类,标记“包名”与 “后缀名”
*****************************************************/

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;

namespace ABFw
{
    public class AutoSetAssetBundleLabel 
    {
        /// <summary>
        /// 设置AB包名
        /// </summary>
        [MenuItem("AssetBundleTools/Set AB Label")]
        public static void SetABLabel() {

            // 需要做标记的根目录
            string strNeedSetLabelRoot = string.Empty;
            // 目录信息(场景目录信息数组,表示所有根目录下场景目录)
            DirectoryInfo[] directoryDIRArray = null;

            // 清空无用的 AB 标记
            AssetDatabase.RemoveUnusedAssetBundleNames();


            // 定义需要打包资源的文件夹根目录
            strNeedSetLabelRoot = PathTools.GetABResourcesPath();
            //Debug.Log("strNeedSetLabelRoot = "+strNeedSetLabelRoot);

            DirectoryInfo dirTempInfo = new DirectoryInfo(strNeedSetLabelRoot);
            directoryDIRArray = dirTempInfo.GetDirectories();

            //2、 遍历本场景目录下所有的目录或者文件
            foreach (DirectoryInfo currentDir in directoryDIRArray)
            {
                //2.1:遍历本场景目录下所有的目录或者文件
                // 如果是目录,则继续“递归”访问里面的文件,直到定位到文件
                string tmpScenesDir = strNeedSetLabelRoot + "/" + currentDir.Name;       // Unity /xx/xx 全路径
                //DirectoryInfo tmpScenesDirInfo = new DirectoryInfo(tmpScenesDir);
                int tmpIndex = tmpScenesDir.LastIndexOf("/");
                string tmpScenesName = tmpScenesDir.Substring(tmpIndex +1);         // 场景名称
                //Debug.Log("tmpScenesDir = "+ tmpScenesDir);

                //2、2 递归调用方法,找到文件,则使用 AssetImporter 类,标记“包名”与 “后缀名”
                JudgeDirOrFileByRecursive(currentDir, tmpScenesName);
            }

            // 刷新
            AssetDatabase.Refresh();

            // 提示信息,标记包名完成
            Debug.Log("AssetBundle 本次操作设置标记完成");
        }

        /// <summary>
        /// 递归判断判断是否是目录或文件
        /// 是文件,修改 Asset Bundle 标记
        /// 是目录,则继续递归
        /// </summary>
        /// <param name="fileSystemInfo">当前文件信息(文件信息与目录信息可以相互转换)</param>
        /// <param name="sceneName">当前场景名称</param>
        private static void JudgeDirOrFileByRecursive(FileSystemInfo fileSystemInfo, string sceneName) {
            // 调试信息
            //Debug.Log("currentDir.Name = " + fileSystemInfo.Name);
            //Debug.Log("sceneName = " + sceneName);

            // 参数检查
            if (fileSystemInfo.Exists == false)
            {
                Debug.LogError("文件或者目录名称:"+fileSystemInfo+" 不存在,请检查");
                return;
            }

            // 得到当前目录下一级的文件信息集合
            DirectoryInfo directoryInfoObj = fileSystemInfo as DirectoryInfo;           // 文件信息转为目录信息
            FileSystemInfo[] fileSystemInfoArray = directoryInfoObj.GetFileSystemInfos();

            foreach (FileSystemInfo fileInfo in fileSystemInfoArray)
            {
                FileInfo fileInfoObj = fileInfo as FileInfo;

                // 文件类型
                if (fileInfoObj != null)
                {
                    // 修改此文件的 AssetBundle 标签
                    SetFileABLabel(fileInfoObj,sceneName);
                }
                // 目录类型
                else {

                    // 如果是目录,则递归调用
                    JudgeDirOrFileByRecursive(fileInfo, sceneName);
                }
            }
        }

        /// <summary>
        /// 给文件打 Asset Bundle 标记
        /// </summary>
        /// <param name="fileInfoObj">文件(文件信息)</param>
        /// <param name="scenesName">场景名称</param>
        static void SetFileABLabel(FileInfo fileInfoObj, string scenesName) {
            // 调试信息
            //Debug.Log("fileInfoObj.Name = " + fileInfoObj.Name);
            //Debug.Log("scenesName = " + scenesName);

            // 参数定义
            // AssetBundle 包名称
            string strABName = string.Empty;
            // 文件路径(相对路径)
            string strAssetFilePath = string.Empty;

            // 参数检查(*.meta 文件不做处理)
            if (fileInfoObj.Extension == ".meta")
            {
                return;
            }

            // 得到 AB 包名称
            strABName = GetABName(fileInfoObj,scenesName);
            // 获取资源文件的相对路径
            int tmpIndex = fileInfoObj.FullName.IndexOf("Assets");
            strAssetFilePath = fileInfoObj.FullName.Substring(tmpIndex);        // 得到文件相对路径


            // 给资源文件设置AB名称以及后缀
            AssetImporter tmpImportObj = AssetImporter.GetAtPath(strAssetFilePath);
            tmpImportObj.assetBundleName = strABName;

            // 判断文件是否是场景文件
            if (fileInfoObj.Extension == ".unity")
            {
                // 定义AB包的场景扩展名
                tmpImportObj.assetBundleVariant = "u3d";
            }
            else
            {
                // 定义AB包的非场景扩展名
                tmpImportObj.assetBundleVariant = "ab";
            }
        }

        /// <summary>
        /// 获取 AB 包的名称
        /// </summary>
        /// <param name="fileInfoObj">文件信息</param>
        /// <param name="scenesName">场景名称</param>
        /// AB 包名形成规则:
        ///     文件AB包名称 = “所在二级目录名称”(场景名称)+“三级目录名称”(类型名称)
        /// <returns></returns>
        static string GetABName(FileInfo fileInfoObj, string scenesName) {
            // 返回AB包名称
            string strABName = string.Empty;

            // win 路径
            string tmpWinPath = fileInfoObj.FullName;
            // 转为 Unity 路径格式
            string tmpUnityPath = tmpWinPath.Replace("\\","/");

            // 定位“场景名称”后面字符位置
            int tmpSceneNamePosition = tmpUnityPath.IndexOf(scenesName) + scenesName.Length;
            // AB 包中 “类型名称”所在区域
            string strABFileNameArea = tmpUnityPath.Substring(tmpSceneNamePosition+1);
            //测试
            //Debug.Log(" strABFileNameArea = " + strABFileNameArea);

            // 非场景资源
            if (strABFileNameArea.Contains("/"))
            {
                string[] tmpStrArray = strABFileNameArea.Split('/');

                //测试
                //Debug.Log("tmpStrArray[0] = "+ tmpStrArray[0]);

                // AB 包名称正式形成
                strABName = scenesName + "/" + tmpStrArray[0];
            }
            // 场景资源
            else {
                // 定义*.unity 文件形成的特殊 AB 包名称
                strABName = scenesName + "/" + scenesName;
            }


            return strABName;
        }

    }//class_End
}

 

2、PathTools

/****************************************************
文件:PathTools.cs
作者:仙魁XAN
邮箱:https://blog.csdn.net/u014361280 
日期:2020/08/14 17:11:52
功能:AB框架的 路径工具类
    1、路径常量
    2、路径方法
*****************************************************/

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

namespace ABFw
{

    public class PathTools 
    {
        /* 路径常量 */
        public const string AB_RESOURCES = "AB_Resources";  // 打包AB包根路径

        /* 路径方法 */

        /// <summary>
        /// 得到 AB 资源的输入目录
        /// </summary>
        /// <returns></returns>
        public static string GetABResourcesPath() {
            return Application.dataPath + "/" + AB_RESOURCES;
        }

        /// <summary>
        /// 获得 AB 包输出路径
        ///     1\ 平台(PC/移动端等)路径
        ///     2\ 平台名称
        /// </summary>
        /// <returns></returns>
        public static string GetABOutPath() {
            return GetPlatformPath() + "/" + GetPlatformName();
        }

        /// <summary>
        /// 获得平台路径
        /// </summary>
        /// <returns></returns>
        private static string GetPlatformPath() {

            string strReturenPlatformPath = string.Empty;

            switch (Application.platform)
            {
                
                case RuntimePlatform.WindowsPlayer:           
                case RuntimePlatform.WindowsEditor:
                    strReturenPlatformPath = Application.streamingAssetsPath;

                    break;
                case RuntimePlatform.IPhonePlayer:         
                case RuntimePlatform.Android:
                    strReturenPlatformPath = Application.persistentDataPath;
                    
                    break;
              
                default:
                    break;
            }

            return strReturenPlatformPath;
        }

        /// <summary>
        /// 获得平台名称
        /// </summary>
        /// <returns></returns>
        public static string GetPlatformName()
        {
            string strReturenPlatformName = string.Empty;

            switch (Application.platform)
            {

                case RuntimePlatform.WindowsPlayer:
                case RuntimePlatform.WindowsEditor:
                    strReturenPlatformName = "Windows";

                    break;
                case RuntimePlatform.IPhonePlayer:
                    strReturenPlatformName = "IPhone";

                    break;
                case RuntimePlatform.Android:
                    strReturenPlatformName = "Android";

                    break;

                default:
                    break;
            }

            return strReturenPlatformName;
        }

        /// <summary>
        /// 返回 WWW 下载 AB 包加载路径
        /// </summary>
        /// <returns></returns>
        public static string GetWWWAssetBundlePath() {
            string strReturnWWWPath = string.Empty;

            switch (Application.platform)
            {

                case RuntimePlatform.WindowsPlayer:
                case RuntimePlatform.WindowsEditor:
                    strReturnWWWPath = "file://"+GetABOutPath();

                    break;
                case RuntimePlatform.IPhonePlayer:
                    strReturnWWWPath = GetABOutPath()+"/Raw/";

                    break;

                case RuntimePlatform.Android:
                    strReturnWWWPath = "jar:file://"+GetABOutPath();

                    break;

                default:
                    break;
            }

            return strReturnWWWPath;
        }

    }//Class_End
}

 

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
### 回答1: Unity AssetBundleUnity 引擎中一种用于打包和管理资源的机制。通过使用 AssetBundle,我们可以将资源打包成一个个独立的,然后在运行时根据需要动态加载和卸载这些资源,从而实现游戏资产的按需加载,节省内存和加载时间。 进阶的实现 AssetBundle 框架括以下步骤: 1. 资源类与打包:根据游戏的需求,将资源按照类型进行类,并使用 Unity打包工具将资源打包成 AssetBundle。 2. 资源加载与管理:在游戏运行时,通过 AssetBundle 的加载接口加载需要的资源,可以使用 WWW 或 UnityWebRequest 进行加载,并使用 AssetBundleManifest 来管理加载的 AssetBundle。 3. 资源缓存与卸载:加载并使用资源后,可以将资源缓存在内存中,以便后续快速访问。当资源不再需要时,可以使用 Unload 方法释放资源,以节省内存。 4. 异步加载与加载进度:为了防止资源加载阻塞游戏主线程,可以使用异步加载的方式加载资源,并通过回调函数获取加载进度信息,以便显示加载界面或进度条。 5. 资源更新与热更:在游戏发布后,如果需要更新或替换某些资源,可以使用 AssetBundle 的版本控制机制,根据服务器资源版本信息判断是否需要更新,并进行资源差异化下载和替换。 6. 跨平台适配:Unity AssetBundle 可以在不同平台(如 Windows、iOS、Android)上使用相同的打包和加载方式,因此可以方便地实现跨平台适配。 通过以上步骤,我们可以实现一个简单的 AssetBundle 框架,实现资源的按需加载、缓存、卸载、异步加载和更新等功能。这样可以大幅减少游戏的内存占用和加载时间,提高游戏性能和用户体验。 ### 回答2: Unity assetbundleUnity引擎中用于打包和加载资源的一种方式。在进阶简单实现assetbundle框架中,我们需要完成以下几个步骤: 1.资源打包:首先,我们需要将需要打包资源准备好,括场景、模型、纹理、音效等。然后,使用Unity的AssetBundle API对这些资源进行打包。这一步的关键是给资源设置正确的AssetBundleName和Variant。 2.资源加载:在游戏运行时,我们可以通过AssetBundleManager来加载和管理assetbundle资源。AssetBundleManager是一个自定义的管理器类,使用字典来存储已加载的assetbundle,以便快速获取。 3.动态加载:使用AssetBundleManager加载资源后,可以通过AssetBundleManager提供的接口来实例化、替换、销毁已加载的资源。在需要使用资源的地方,使用Instantiate方法来实例化预制体,或者直接使用LoadAsset方法来加载非预制体资源。加载完成后,可以使用UnityEngine.Object类型来获取具体的资源。 4.资源卸载:当资源不再需要使用时,可以调用AssetBundleManager提供的接口来卸载资源。这样,可以释放内存并减少资源的加载数量。需要注意的是,在卸载资源时,需要考虑其他依赖资源的情况,避免出现因卸载资源而导致其他资源无法使用的问题。 5.异常处理:在加载资源的过程中,可能会出现一些异常情况,例如资源不存在、加载失败等。我们需要在框架中做好异常处理的逻辑,在这些情况下给出合适的提示信息,并采取相应的措施,以保证游戏的正常运行。 综上所述,一个简单的assetbundle框架的实现资源打包、加载、动态加载、资源卸载以及异常处理等步骤。这样的实现可以提高游戏的性能和加载速度,减少内存占用,并且便于资源的管理和更新。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

仙魁XAN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值