【Unity】热更新学习笔记-热更新

热更实操

配置

先展示一下配置,具体如何配置查看上一篇文章

与上一篇文章设置的一样

前置准备

  • 切换成安卓平台
  • 删除./ServerData/文件夹和./Library/com.unity.addressables/aa/文件夹

经测试:

  • 直接使用Build Profiles的Build时,也会进行Build -> NewBuild -> Default Build Script生成资产文件

  • Addressable Asset Settings -> Build Remote Catalog是非常重要的设置,进行以下实验时需时刻注意本地缓存文件。

    • 所有的资产都在Default Local Group中:
      • 未勾选:不会向服务器发送请求,物体能正常加载。(可以在包体路径中找到本地资产)
      • 勾选+Local:不会向服务器发送请求,物体能正常加载(可以在包体路径中找到本地资产,且多了catalog_0.1.0.bincatalog_0.1.0.hash文件,这两个文件是有版本后缀的,不要与catalog.bincatalog.hash混淆了)
      • 勾选+Remote:向服务器发送请求,若请求失败,则不会加载物体(即使local中有资产);请求成功后,若没有更新则直接使用本地本地资源;若有更新则将更新缓存到本地。(可以在包体路径中找到本地资产,没有catalog文件)。
    • 所有的资产都在Remote Group中:
      • 未勾选:向服务器发送请求(报错:无法链接到目标地址),且无法加载Remote Group中的物体。(并未在包体中找到ServerData文件,且包体本地中也未找到任何资产),只有将打包生成的ServerData上传服务器才能显示图片。
      • 勾选+Local:向服务器发送请求(报错:无法链接到目标地址),且无法加载Remote Group中的物体。(同样没找到资产文件,但本地路径下多了两个catalog文件)
      • 勾选+Remote:向服务器发送请求,若有更新则将更新缓存到本地;

    总结:

    • 经测试Android与Window效果一致(需注意缓存文件)。
    • 直接放置在Remote Group中的资产不管如何设置都会向服务器发送请求。因为该组的资产只build在ServerData中,用户获取的包体里并没有该组的资产。用户只能从服务器上下载。
    • 另外有一个特殊情况:”勾选+Remote”时,用户打开游戏的时候会先向服务器确认是否有更新(如果请求失败不会显示图片),然后再显示图片(没有更新:直接显示本地的;有更新:将远程的资产下载到本地)。具体流程如下图

另外发现一个很奇怪的问题:

在删除Library编译文件,和C:\Users\coffeeofnosugar\AppData\LocalLow\Unity\DefaultCompany_XLuaProject本地缓存之后。如果你之前向服务器获取过这张图片,即使服务器上什么都没有,打开游戏时也能正常显示图片。应该是本地缓存了,但作者还为找到存在什么位置。

上方的流程图和下方的测试是没毛病的


Local Group热更新

具体流程就像上图,这里我们具体操作一下,Windows方便查看log和本地缓存,所以先还是使用Windows版

经上面的测试,我们只需测试,只有在设置成”勾选+Remote”的时候才会向服务器发送请求,设置如下

打包后开启游戏

  • 即使Remote组中没有物体,也会向服务器发送请求

  • 即使物体是在Local Group中,服务端上没有该物体,依然不会加载

  • 报错内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    Unable to open archive file: D:/UnityProject/XLuaProject/Build/XLuaProject_Data/StreamingAssets/aa/StandaloneWindows64/defaultlocalgroup_assets_all_57c55f293171dd03a4c62f3e626f64b9.bundle
    RemoteProviderException : Invalid path in AssetBundleProvider: 'D:/UnityProject/XLuaProject/Build/XLuaProject_Data/StreamingAssets/aa\StandaloneWindows64\defaultlocalgroup_assets_all_57c55f293171dd03a4c62f3e626f64b9.bundle'.
    OperationException : GroupOperation failed because one of its dependencies failed
    RemoteProviderException : Invalid path in AssetBundleProvider: 'D:/UnityProject/XLuaProject/Build/XLuaProject_Data/StreamingAssets/aa\StandaloneWindows64\defaultlocalgroup_assets_all_57c55f293171dd03a4c62f3e626f64b9.bundle'.
    System.Exception: Dependency Exception ---> UnityEngine.ResourceManagement.Exceptions.OperationException: GroupOperation failed because one of its dependencies failed ---> UnityEngine.ResourceManagement.Exceptions.RemoteProviderException: RemoteProviderException : Invalid path in AssetBundleProvider: 'D:/UnityProject/XLuaProject/Build/XLuaProject_Data/StreamingAssets/aa\StandaloneWindows64\defaultlocalgroup_assets_all_57c55f293171dd03a4c62f3e626f64b9.bundle'.

    --- End of inner exception stack trace ---
    --- End of inner exception stack trace ---
    Failed to read data for the AssetBundle 'aa\StandaloneWindows64\defaultlocalgroup_assets_all_57c55f293171dd03a4c62f3e626f64b9.bundle'.
    OperationException : ChainOperation failed because dependent operation failed
    System.Exception: Dependency Exception ---> UnityEngine.ResourceManagement.Exceptions.OperationException: GroupOperation failed because one of its dependencies failed ---> UnityEngine.ResourceManagement.Exceptions.RemoteProviderException: RemoteProviderException : Invalid path in AssetBundleProvider: 'D:/UnityProject/XLuaProject/Build/XLuaProject_Data/StreamingAssets/aa\StandaloneWindows64\defaultlocalgroup_assets_all_57c55f293171dd03a4c62f3e626f64b9.bundle'.

    --- End of inner exception stack trace ---
    --- End of inner exception stack trace ---

提示找不到下面的路径,但奇怪的是这路径是确实是我们的本地路径,为什么没有资源呢./XLuaProject_Data/StreamingAssets/aa/StandaloneWindows64/defaultlocalgroup_assets_all_57c55f293171dd03a4c62f3e626f64b9.bundle

该路径下确实有Default Local Group,但并不是报错所要的内容。

上传资产

因为我们选择的是”勾选+Remote”,所以会在./ServerData/StandaloneWindows64/路径下生成两个catalog文件。将这个两个文件上传到服务器,后再次打开游戏——加载成功,并且没有报错。

这时很奇怪的一幕就会发现,当我们把服务器上的资产删掉后,再次打开游戏。服务端会接受到请求,但物体能正常加载,且并不是简单的缓存,而是直接读取的客户端的本地资产。

此时我们将锤子更换成弓箭

使用Update a Previous Build重新打包

更新资产

此时直接打开游戏,依然是锤子。我们需要将新的ServerData包体上传到服务器,再打开游戏,但最后图片加载失败,报错内容:

1
Unable to open archive file: D:/UnityProject/XLuaProject/Build/XLuaProject_Data/StreamingAssets/aa/StandaloneWindows64/defaultlocalgroup_assets_assets/game/art/sprites_0d30367a8dddecfef828636864c4bae5.bundle

正确做法:

  1. 将更改的资产添加到Remote Group中
  2. 更新包体,并上传到服务器

再次打开游戏,能看到图片变成弓箭了,并且在服务端log上能看到下载.bundle的log

此时我们能看到C:\Users\coffeeofnosugar\AppData\LocalLow\Unity\DefaultCompany_XLuaProject路径下多了一个文件夹,这个就是刚才从服务器上下载下来的缓存文件,测试以下两种情景。

  • 再次打开游戏,向服务器发送请求获取catalog,得知要使用弓箭图片,使用本地缓存资产。
  • 删掉缓存文件,打开游戏,向服务器发送请求获取catalog,得知要使用弓箭图片,重新下载。

得知,热更之后,如果有本地缓存,则限优先使用本地缓存,若没有没有本地缓存则向服务端下载。

再来测试以下四种情景,先把缓存文件下载下来:

  • 保留服务器的catalog文件、删除资产文件,保留缓存文件:启动游戏,能显示弓箭——使用的本地缓存。
  • 保留服务器的catalog文件、删除资产文件,并删除缓存文件:启动游戏,弓箭显示失败,能看到服务器上获取弓箭的资产404
  • 删除服务器的catalog资产文件,但保留缓存文件:启动游戏,显示弓箭——使用本地缓存。
  • 删除服务器的catalog资产文件,且删除缓存文件:启动游戏,弓箭和锤头都不显示了,且在退出游戏时会卡死无响应。

可以得知,一旦游戏热更之后,如果服务器无法访问,则游戏无法继续运行

小结

最关键的点是:最开始物体在Local Group中,在需要实现热更的时候将其移动到Remote Group中。

这种方式可以很大程度上的缓解服务器的压力,让玩家在下载游戏时并不是所有内容都从服务器上拉取,很适合小工作室。

经过新项目测试,发现Local Group中的物体在打开游戏时,如果服务器上没有catalog文件,图片是不会显示的。所以如果想要通过将资产放在local中,从而完全避免搭建服务器是不可能的。


Remote Group热更新

上一篇文章探讨了如果设置成”勾选+Retmoe”时Retmoe Group组中的热更新情况。

这里用流程图概括一下


总结

上面过程可能比较长,主要是为了测试效果,以及每一步的表现,这里简单的概括一下总流程

  1. 物体最开始可以直接放置在Local中,也可以放置在Remote中
    • Local:虽然也会访问服务器,但只是检查更新,并不会下载任何东西
    • Remote:该组的内容都是从服务器上拉取下来的
  2. 若需要热更新
    • Local:将其从local组中添加到remote组中,再执行Update a Previous Build,将新生成的文件上传到服务器上
    • Remote:修改好后直接执行Update a Previous Build,并将新生成的文件上传到服务器上
  3. 真机测试