Unity手游开发:Addressables之二、资源更新模式

Group设置中可以配置资源的更新模式,有两个配置决定资源的更新模式:LoadPath、UpdateRestriction

LoadPath:

LoadPath有local和remote之分,remote是指远程地址,比如http请求,而local则是本地加载。AAS对LoadPath选项的设计初衷就是,需要更新的资源就用remote方式,不需要更新的资源使用local方式。

UpdateRestriction:

UpdateRestriction也有两种选项:Can Change Post Release、Can not Change Post Release,即发布后可更改(NonStatic)、发布后不可更改(Static)。

比如GroupA中有资源A发生了变化,需要进行更新:

若GroupA设置为NonStatic,则代表将资源A下载下来后Group结构不作任何变化,但会下载新GroupA的bundle,即可理解为直接替换资源,相当于全量更新(前提是Group是Pack Together方式)。

而若GroupA设置为Static则代表原Group的资源不可修改,在下载A资源的同时将更新Catalog中GroupA的结构,将A资源移出GroupA,放入新增的Group组中(新增ContentUpdate组,需配合AAS工具栏的Check for Content Update Restriction工具使用),只会下载新增的Group:ContentUpdate(包含资源A和其依赖项),相当于增量更新。

新增的ContentUpdate组:

image

综上,一共有4种模式组合可供使用,即local-static,local-nonstatic,remote-staticremote-nonstatic。其中local-nostatic没有意义,排除这种组合。其实local模式其实设计上是不允许更新的,但是AAS还是做了更新兼容,于是local-static配合Check for Content Update Restriction也是可以增量更新的。

我们列出local-static、remote-static、remote-nonstatic的效果:

  • local-static:打包时带入开发包中。更新时走增量更新。

  • remote-static:打包时放在服务器,不带入开发包。更新时走增量更新。

  • remote-nonstatic:打包时放在服务器,不带入开发包。更新时走全量更新。

由于static的增量更新会修改Group的结构,若采用static方式,考虑一种极限状态,即所有的资源都进行过更新,那么最后整个项目的资源Group应该会全部变成ContentUpdate组:ContentUpdate、ContentUpdate1、ContentUpdate2…,这样的话我们的分组策略就完全被打乱了,所以第一时间排除static模式。

所以,我们剩下的方案就只有remote-nonstatic模式。但是我们期望的更新方式是打包时能带入开发包,而不是边玩边下。事实上,可以用AAS的InternalIdTransformFunc函数定制出这样的机制:打包时,强行把remote打出的catalog和资源文件放入包体资源加载时,优先判断使用本地包体中的资源

AAS提供了InternalIdTransformFunc函数,来帮助开发者自定义修改运行时的资源索引地址,比如请求本地资源A的地址InternalIdTransformFunc返回值为“Assets/a.prefab”,在该函数中可修改为返回“Assets/b.prefab”以重定向使用b资源。

官方示例代码如下:

    void Start()
    {
        Addressables.ResourceManager.InternalIdTransformFunc = TransformFunc;
    }
    
    string TransformFunc(IResourceLocation location)
    {
        //Implement a method that gets the base url for a given location
        string baseUrl = GetBaseURL(location);
    
        //Get the url you want to use to point to your current server
        string currentUrlToUse = GetCurrentURL();
    
        return location.InternalId.Replace(baseUrl, currentUrlToUse);
    }

因此,我们可以设置GroupBundle Naming Mode配置项为Use Hash of AssetBundle,配合InternalIdTransformFunc函数实现优先使用本地资源的设计。主要思路为:拦截资源地址请求,替换成开发包体内本地资源地址(随包资源地址,非缓存地址),再判断本地是否有该最新资源,有的话就直接返回本地资源地址。而判断资源是否为最新资源,则只需要资源构建时使用Use Hash of AssetBundle(为了避免暴露资源名称,我们不使用Append Hash to Filename)配置对资源以hash值命名即可,这样只要路径存在,资源就是最新的。

实现代码如下:

    private static string InternalIdTransformFunc(UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation location)
    {
        //判定是否是一个AB包的请求(真机运行和exist building模式走这里)
        if (location.Data is AssetBundleRequestOptions)
        {
    #if UNITY_EDITOR
            var path = string.Format("{0}/{1}/{2}/{3}", Application.dataPath.Replace("/Assets", ""), Addressables.RuntimePath, UnityEditor.EditorUserBuildSettings.activeBuildTarget, location.PrimaryKey);
    #elif UNITY_ANDROID
            var path = string.Format("{0}/Android/{1}", Addressables.RuntimePath, location.PrimaryKey);
    #else
            var path = string.Format("{0}/iOS/{1}", Addressables.RuntimePath, location.PrimaryKey);
    #endif
            if (FileUtils.IsFileExists(path))
            {
                return path;
            }
        }
        return location.InternalId;
    }

使用non-static更新模式,若Group使用Pack Together打包模式,则更新时会更新整个Group的资源,而使用Pack Separate打包模式,则加载时由于bundle过多,会降低加载速度。因此,该方式对Group的颗粒度划分有更高的要求。相关内容可见《六、Group控制AB包颗粒度策略》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值