Lua、AB包热更新总结

1.AB包热更新

(1)AB包是一种特定的压缩文件,可以放模型贴图音效等等

(2)Resources目录下打包时只读 无法修改;而AB包存储的位置是自定义的,能够动态更新,同时可以决定资源包初始的大小。

(3)热更新流程:客户端自带很少的默认资源,通过获取资源服务器地址,再通过文件对比资源服务器的资源,检测哪些是需要下载的,就是AB包。
2.AB包资源打包

(1)官方提供的工具:Asset Bundle Browser

(2)工具的参数

(3)AB包生成的文件
3.AB包资源加载

csharp 复制代码
void Start()
    {
        //加载AB包
        AssetBundle ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/model");
        //加载AB包中的指定资源
        //如果只使用名字加载 可能会出现类型分不清
        GameObject go2 = ab.LoadAsset("Cube");
        //建议使用泛型加载 或者 指定类型加载
        GameObject go2 = ab.LoadAsset<GameObject>("Cube");
        GameObject go = ab.LoadAsset("Cube", typeof(GameObject)) as GameObject;   
        Instantiate(go);
        
		//同一个AB包不能够重复加载
		
		//卸载单个的资源
        //true会把已经加载的资源也卸载 false则只卸载AB包的资源
        ab.Unload(true);
        //卸载所有加载的AB包
        //false则只卸载AB包的资源
        AssetBundle.UnloadAllAssetBundles(true);
    }

4.依赖包

(1)一个资源用到了其他AB包中的资源 此时 如果只加载这个资源 不加载依赖资源的AB包 就会出现材质丢失 所以又要加载该资源 也要加载其他AB包 但是依赖资源太多就会很麻烦,所以使用主包加载这些依赖资源

(2)使用该方法的缺点就是,会加载出全部的依赖资源,但不知道谁需要用,A依赖1资源,B依赖2资源,加载的时候会加载1和2资源

5.AB管理器的同步加载和异步加载(目的就是更方便的调用)

csharp 复制代码
public class ABManager : BasePanelMono<ABManager>
{
    //让外部更方便的加载

    //主包
    private AssetBundle mainAB = null;
    //依赖包
    private AssetBundleManifest mainfest = null;

    //存储加载过的ab
    private Dictionary<string, AssetBundle> abDic = new Dictionary<string, AssetBundle>();

    private string Path
    {
        get
        {
            return Application.streamingAssetsPath + "/";
        }
    }
    private string MainABName
    {
        get
        {
#if UNITY_IOS
            return "IOS";
#elif UNITY_ANDROID
            return "Android";
#else
            return "PC";
#endif
        }
    }

    public void LoadAB(string abName)
    {
        //加载主包 和 主包中的固定文件
        //根据固定文件 获取该AB包的依赖资源 加入字典中
        //判断字典中是否存在该AB包 加入字典中
        if (mainAB == null)
        {
            mainAB = AssetBundle.LoadFromFile(Path + MainABName);
            mainfest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
        }
        AssetBundle ab = null;
        string[] str = mainfest.GetAllDependencies(abName);
        for (int i = 0; i < str.Length; i++)
        {
            //判断依赖是否被加载过
            if (!abDic.ContainsKey(str[i]))
            {
                ab = AssetBundle.LoadFromFile(Path + str[i]);
                abDic.Add(str[i], ab);
            }
        }
        if (!abDic.ContainsKey(abName))
        {
            ab = AssetBundle.LoadFromFile(Path + abName);
            abDic.Add(abName, ab);
        }
    }
    /// <summary>
    /// 同步加载
    /// </summary>
    /// <param name="abName"></param>AB包的名字
    /// <param name="resName"></param>目标资源名字
    /// <returns></returns>
    public Object LoadRes(string abName,string resName)
    {
        LoadAB(abName);
        Object obj = abDic[abName].LoadAsset(resName);
        if (obj is GameObject)
            return Instantiate(obj);
        else
            return obj;
    }
    public Object LoadRes(string abName, string resName,System.Type type)
    {
        LoadAB(abName);
        Object obj = abDic[abName].LoadAsset(resName,type);
        if (obj is GameObject)
            return Instantiate(obj);
        else
            return obj;
    }
    public T LoadRes<T>(string abName, string resName) where T : Object
    {
        LoadAB(abName);
        T obj = abDic[abName].LoadAsset<T>(resName);
        if (obj is GameObject)
            return Instantiate(obj);
        else
            return obj;
    }

	//异步加载
    public void LoadResAsync(string abName, string resName,UnityAction<Object> callback)
    {
        StartCoroutine(IELoadResAsync(abName, resName, callback));
    }

    private IEnumerator IELoadResAsync(string abName, string resName, UnityAction<Object> callback)
    {
        LoadAB(abName);
        AssetBundleRequest abr = abDic[abName].LoadAssetAsync(resName);
        yield return abr;//等待abr加载完毕

        //如果abr的资源是gameobject就实例化 不是就返回出去
        if (abr.asset is GameObject)
            callback(Instantiate(abr.asset));
        else
            callback(abr.asset);
        yield return null;
    }
    //单个AB卸载
    public void Unload(string abName)
    {
        if(abDic.ContainsKey(abName))
        {
            abDic[abName].Unload(false);
            abDic.Remove(abName);
        }
    }
    //全部卸载
    public void UnloadAll()
    {
        AssetBundle.UnloadAllAssetBundles(false);
        abDic.Clear();
        mainAB = null;
        mainfest = null;
    }
}
相关推荐
侃侃_天下2 天前
最终的信号类
开发语言·c++·算法
echoarts2 天前
Rayon Rust中的数据并行库入门教程
开发语言·其他·算法·rust
Aomnitrix2 天前
知识管理新范式——cpolar+Wiki.js打造企业级分布式知识库
开发语言·javascript·分布式
每天回答3个问题2 天前
UE5C++编译遇到MSB3073
开发语言·c++·ue5
伍哥的传说2 天前
Vite Plugin PWA – 零配置构建现代渐进式Web应用
开发语言·前端·javascript·web app·pwa·service worker·workbox
小莞尔2 天前
【51单片机】【protues仿真】 基于51单片机八路抢答器系统
c语言·开发语言·单片机·嵌入式硬件·51单片机
我是菜鸟0713号2 天前
Qt 中 OPC UA 通讯实战
开发语言·qt
JCBP_2 天前
QT(4)
开发语言·汇编·c++·qt·算法
Brookty2 天前
【JavaEE】线程安全-内存可见性、指令全排序
java·开发语言·后端·java-ee·线程安全·内存可见性·指令重排序
百锦再2 天前
[特殊字符] Python在CentOS系统执行深度指南
开发语言·python·plotly·django·centos·virtualenv·pygame