unity 打AB包中遇到的坑以及一些心得

Posted xiaoLongww

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了unity 打AB包中遇到的坑以及一些心得相关的知识,希望对你有一定的参考价值。

unity 打AB包中遇到的坑以及一些心得

unity踩坑之旅


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

依旧很突然,昨晚临睡前突然收到老板的要求:把指定的美术资源打个AB包。本来想着这不小菜一碟,结果今天差点没把我噎到,特此记录


一、AB包是什么,基础引入?

unity官方写得很好,我就不班门弄斧了。如果太难懂的话,也可以上论坛看看各位大佬的见解,这里就不赘述了。
unity的打AB包教程

二、AB包怎么操作,我的见解?

1.自己写编辑器脚本 (简单快捷)

步骤就在里面的4-8点
unity的打AB包教程

在Editor文件夹创建一个脚本,用于创建AB包

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

public class bundle

    [MenuItem("AssetsBundle/Build AssetBundles")]
    static void BuildAllAssetBundles()//进行打包
    
        string dir = "AssetBundles";
        //判断该目录是否存在
        if (Directory.Exists(dir) == false)
        
            Directory.CreateDirectory(dir);
        
        //参数一为打包到哪个路径,参数二压缩选项  参数三 平台的目标
        BuildPipeline.BuildAssetBundles(dir, BuildAssetBundleOptions.None, BuildTarget.android);
    

下面这个是加载AB包GameObject到场景,在非Editor文件夹即可

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

public class BundledObj : MonoBehaviour


    public string astName = "hello";
    public string ziyuan = "GameObject";

    // Start is called before the first frame update
    void Start()
    
        AssetBundle loc = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, astName));

        GameObject a = loc.LoadAsset<GameObject>(ziyuan);
        Instantiate(a);
        loc.Unload(false);
    
    

   


2.使用asset bundle browser (unity2020开始需要从github下载)

com.unity.assetbundlebrowser

3.使用addressable (最新、可寻址,据说unity在这个插件上下了大功夫,包含了发布AB包到服务器,以及如何像本地一样使用远程包)

林大佬对addressable的介绍

三、AB包的一些坑,我的解决?

坑记录:(以下坑是使用上述方法1和方法2遇到)

1.打AB包坑之一:打包、加载包的unity版本需要相同,否则读取时会报错

unity Unable to read header from archive file:

补充:这个错误是在使用unity2020.3.20f1c1打包,用2020.3.8f1c1加载报错;但是使用unity2019.4.4f1打包,2020.3.8f1c1加载又正常。所以结论修改为——unity2020以上请使用相同版本打包与加载
20221111-2310再次补充:使用unity2020.3.20f1c1打包,用2020.3.8f1c1加载,发现没有报错。。。。。。。然而上午的时候疯狂报错,只能说人品不好,吃完饭回来什么都解决了。。

2.变成粉色

粉色解决

有不生效的shader应该怎么办?添加到里面也没用,需要加载方也要有shader才行;试过打包shader也没用

3.另外,standard的transparent不起作用?打包前看还正常,打包后没有透明效果了;也是目前无解


总结

提示:这里对文章进行总结:

AB包的研究还要继续,有时间再继续补充,欢迎各位朋友评论

unity5打包机制下,一种资源打ab和资源管理的方案

unity5打包机制下,一种资源打ab和资源管理的方案。
1.打ab:
  1.设置平台
  2.清楚所有资源的assetbundlename:
    string[] abNameArr = AssetDatabase.GetAllAssetBundleNames();
    AssetDatabase.RemoveAssetBundleName(abNameArr[i],true);
  3.创建ab目录
  4.根据配置把需要打包的资源找出来,对每一个setAbName
  5.调用BuildPipeline.BuildAssetBundles(ab文件夹路径,BuildAssetBundleOptions.DeterministicAssetBundle,EditorUserBuildSettins.activeBuildTarget);
  6.完成,但这里要对第4点做一些说明,因为依赖资源:
    我们可以选择一种简单粗暴的方式处理依赖资源:搞几个公共依赖assetbundle,把一些公共资源打到这几个公共ab中,具体就是:
    在第4步,我们设置一个资源的abName后,对其依赖进行:
      string[] deps = AssetDatabase.GetDependencies(sourcePath);
      if (deps[i] 需要打入公共依赖1)
      AssetImporter aIt = AssetImporter.GetAtPath(deps[i]);
      aIt.assetBundleName = 公共依赖1.assetBundle.
      if (deps[i] 需要打入公共依赖2)
      ...
    其他的依赖就不必继续分离了,即打到各个资源的ab里,虽然会增加ab的大小,但依赖资源管理会方便很多。
2.资源管理:
  先加载各个公共依赖到内存,并且一直引用这不unload,其他正式资源加载时自己加载对应的ab即可,无需加载依赖了。
具体代码如下:(启动游戏先加载公共依赖,一样的加载方式)

        //原始资源引用
        UnityEngine.Object m_ResGameObj = null;
        //3个异步加载句柄:
        //资源包加载句柄,引用www加载ab时结果
        WWW m_LoadHandle = null;
        //资源包加载请求,引用loadfromfileasync和loadfrommemoryasync的结果
        AssetBundleCreateRequest m_Request = null;
        //资源加载请求,引用loadassetasync结果
        AssetBundleRequest m_AssetRequest = null;
        //资源包,引用各种加载出来的资源包
        AssetBundle m_AssetBundle = null;
        //资源相对路径且没有后缀,作为基础路径,方便后续的各种拼接
        public string V_AssetPath = null;//是否采用异步
        public bool V_UseAsync = true;
        //加载优先级
        public int V_Priority = 0;
     
/// <summary> /// 加载图片只能用www方式 /// </summary> /// <param name="path">绝对路径</param> /// <returns></returns> IEnumerator LoadBundleImpImage(string path) { m_LoadHandle = new WWW(PathHelper.GetInstance().F_AddFilePro(path)); yield return m_LoadHandle; if (m_LoadHandle != null && string.IsNullOrEmpty(m_LoadHandle.error) && m_LoadHandle.assetBundle != null) { m_AssetBundle = m_LoadHandle.assetBundle; string[] assets = m_AssetBundle.GetAllAssetNames(); m_ResGameObj = m_AssetBundle.LoadAsset(assets[0]); } else if (m_LoadHandle != null && string.IsNullOrEmpty(m_LoadHandle.error) && m_LoadHandle.texture != null) { m_ResGameObj = m_LoadHandle.texture; } if (m_LoadHandle != null) m_LoadHandle.Dispose(); m_LoadHandle = null; } /// <summary> /// 加载资源imp /// </summary> /// <returns></returns> IEnumerator LoadResImp() { ResourceRequest request = Resources.LoadAsync(V_AssetPath); yield return request; if (request != null && request.asset != null) { m_ResGameObj = request.asset; } m_AssetBundle = null; }      /// <summary> /// 加载bundle /// </summary> /// <param name="path">绝对路径</param> /// <returns></returns> IEnumerator LoadBundleImp(string path) { m_Request = AssetBundle.LoadFromFileAsync(path); yield return m_Request; if (m_Request != null && m_Request.assetBundle != null) { m_AssetBundle = m_Request.assetBundle; string[] assets = m_AssetBundle.GetAllAssetNames(); m_AssetRequest = m_AssetBundle.LoadAssetAsync(assets[0]); yield return m_AssetRequest; m_ResGameObj = m_AssetRequest.asset; F_SendFinishEvent(); m_Request = null; m_AssetRequest = null; } }
     
//加载入口      public void StartLoadAsset() { string absolutePath = GetPersistentAssetPath(); if (V_UseAsync) { string abPath = string.Empty; if (PathHelper.GetInstance().F_CheckFileExists(absolutePath)) { abPath = absolutePath; } if (abPath.EndsWith(PathHelper.ABFile)) { AssetManager.GetInstance().StartCoroutine(LoadBundleImp(abPath)); } else if (abPath.EndsWith(".jpg") || abPath.EndsWith(".png")) { AssetManager.GetInstance().StartCoroutine(LoadBundleImpImage(abPath)); } else//加载安装包里的文件,或者编辑器下加载资源使用 { AssetManager.GetInstance().StartCoroutine(LoadResImp()); } } else { //同步加载 try { if (m_ResGameObj == null) { m_AssetBundle = null; if (AssetManager.GetInstance().F_IsLoadByAb() && absolutePath.EndsWith(PathHelper.ABFile)) { m_AssetBundle = AssetBundle.LoadFromFile(absolutePath); } if (m_AssetBundle != null) { string[] assets = m_AssetBundle.GetAllAssetNames(); m_ResGameObj = m_AssetBundle.LoadAsset(assets[0]); } else { m_ResGameObj = Resources.Load(V_AssetPath); } } } catch { } } }

 

以上是关于unity 打AB包中遇到的坑以及一些心得的主要内容,如果未能解决你的问题,请参考以下文章

(三)Unity AB包中的依赖项

Unity AssetBundle(3):图集Atlas与AB包

Unity 项目AB资源 重复内容排查

unity5打包机制下,一种资源打ab和资源管理的方案

细说Unity3D——移动平台动态读取外部文件全解析

unity-------------------打包BuildAssetBundles的使用