Unity打包WebGL平台Addressable的缓存

解决Unity WebGL Addressable包缓存问题

最近在开发Unity WebGL项目时,遇到了一个关于Addressable资源包更新的棘手问题。虽然我们每次更新Addressable包时都会生成新的catalog文件(如catalog_0.2.12.json),但浏览器却顽固地使用旧的settings.json文件,导致资源更新失败。

问题分析

问题的根源在于浏览器对静态资源的缓存机制。当我们更新Addressable包时:

  • 新的catalog文件会带上版本号(如catalog_0.2.12.json
  • settings.json文件名始终不变
  • 浏览器会优先使用缓存的旧版settings.json,导致无法获取最新的catalog信息

解决方案

经过一番探索,公司同事找到了一个有效的解决方案:利用Unity WebGL的构建宏,确保每次打包都生成唯一的文件名,从而避免浏览器缓存。

Unity的HTML模板本身就支持以下宏:

Snipaste_2026-02-06_21-00-55

Unity的HTML模板会自动使用这些宏,无需手动替换。例如,模板中的代码:

1
2
3
4
5
6
7
8
9
10
11
<script src="Build/{{{ LOADER_FILENAME }}}"></script>
<script>
createUnityInstance(document.querySelector("#unity-canvas"), {
dataUrl: "Build/{{{ DATA_FILENAME }}}",
frameworkUrl: "Build/{{{ FRAMEWORK_FILENAME }}}",
#if USE_WASM
codeUrl: "Build/{{{ CODE_FILENAME }}}",
#endif
...
});
</script>

这样配置后,每次构建都会生成带有唯一标识的文件,浏览器会下载新文件而不是使用缓存的旧文件。

避免index.html缓存

除了上述宏,还需要确保index.html本身不被缓存。可以在服务器配置中设置适当的缓存策略,或者在HTML文件中添加缓存控制头:

HTML缓存控制

在HTML文件的<head>部分添加以下meta标签:

1
2
3
4
5
<head>
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
</head>

服务器配置

除了HTML标签,最好在服务器层面也配置缓存策略。以下是一些常见服务器的配置示例:

Nginx配置

1
2
3
4
5
6
7
8
9
10
11
12
location / {
# 对index.html设置不缓存
if ($request_filename ~* ^.*index.html$) {
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}

# 对其他资源设置长期缓存
expires 1y;
add_header Cache-Control "public, immutable";
}

注意事项

  1. 版本管理:确保每次构建时更新文件名中的版本号或时间戳,避免重复

  2. CDN配置:如果使用CDN,需要确保CDN也遵循相同的缓存策略

  3. 测试验证:部署后使用浏览器的开发者工具检查网络请求,确保资源加载正确

  4. 回退策略:考虑保留最近几个版本的文件,以便在需要时可以回退

总结

通过使用Unity WebGL的构建宏和适当的缓存控制策略,我们成功解决了Addressable包在WebGL平台上的缓存问题。这种方法简单有效,确保了每次更新都能被浏览器正确加载,提升了用户体验。

如果你在Unity WebGL开发中遇到了类似的问题,希望这个解决方案能对你有所帮助!