关于
Buy Me a Coffee
归档
友链
猫咪
RSS
后台
切换模式
返回顶部
首页
说说
开发
AI
游戏
资源
杂七杂八
首页
说说
开发
AI
游戏
资源
杂七杂八
关于
Buy Me a Coffee
归档
友链
猫咪
RSS
后台
OPPO 快游戏在浏览器复现运行(七)之远程资源离线化
开发
·
游戏
·
今天
LiesAuer
**完全的离线化仅适用于走快游戏 API 的资源,部分资源是直接通过 `img` 标签或者其他方式加载的(最终会 fallback 到 XHR)还是会到本地服务器发起请求。`web.sdk.js` 不对此类资源做特殊拦截处理,做离线化的本意是解决版本更新后在线资源的失效问题,对快游戏做 web 移植本身就需要一个静态服务器托管,所以这个并不算大问题。如果需要完完全全的离线化,可自行对游戏逻辑做魔改拦截。** 针对使用 Cocos Creator 框架制作的游戏,在 `_CCSettings` 中一般能看到以下字段:`remoteBundles`、`bundleVers`,`remoteBundles`是远程 Bundle 列表,`bundleVers`是所有 Bundle 列表,比如: ```js window._CCSettings = { remoteBundles: ["resources"], bundleVers: { internal:"b3cad", b0:"10607", b1:"f37a4", data:"5bf88", resources:"011ae", main:"c0c83" } }; ``` 远程 Bundle 可能会依赖其他 Bundle,为了远程 Bundle 能顺利的加载,需要先通过 `loadBundle` 拿到 Bundle 配置中的 `deps`,统计完整依赖链,再按依赖顺序逐个加载。 ```js async function loadCCBundle(names, unload = false) { names = Array.isArray(names) ? names : [names]; const bundles = Object.create(null); const visited = Object.create(null); const visiting = Object.create(null); const order = []; function unloadBundle(name) { const bundle = cc.assetManager.getBundle(name); if (bundle) { bundle.releaseAll(); cc.assetManager.removeBundle(bundle); } } function loadBundle(name) { return new Promise(function (resolve, reject) { if (unload) { unloadBundle(name); } const exists = cc.assetManager.getBundle(name); if (exists) { resolve(exists); return; } cc.assetManager.loadBundle(name, function (err, bundle) { if (err) { reject(err); return; } resolve(bundle); }); }); } function loadDir(bundle) { return new Promise(function (resolve, reject) { window.qg.consolelog('loadDir start: ' + bundle.name); bundle.loadDir('', function (err) { if (err) { reject(err); return; } window.qg.consolelog(bundle.name + ' resources loaded'); resolve(bundle); }); }); } async function visit(name, stack) { if (visited[name]) { return; } if (visiting[name]) { throw new Error('Circular bundle deps: ' + stack['concat'](name).join(' -> ')); } visiting[name] = true; const bundle = await loadBundle(name); const deps = bundle.deps || []; bundles[name] = bundle; window.qg.consolelog('bundle deps: ' + name + ' -> ' + JSON.stringify(deps)); for (let i = 0; i < deps.length; i++) { await visit(deps[i], stack['concat'](name)); } visiting[name] = false; visited[name] = true; order.push(name); } try { for (let i = 0; i < names.length; i++) { await visit(names[i], []); } window.qg.consolelog('bundle load order: ' + order.join(' -> ')); for (let i = 0; i < order.length; i++) { const name = order[i]; const bundle = bundles[name] || await loadBundle(name); await loadDir(bundle); } window.qg.consolelog('all bundle resources loaded'); } catch (err) { window.qg.consoleerror(err); } } // 然后就可以正式下载远程 Bundle 了 loadCCBundle(window._CCSettings.remoteBundles); ``` 此时应该可以看到控制台已经在疯狂下载资源了,但还不够,因为我们需要将这些资源保存放到本地,以便后续离线化加载。 这时候就到了 `remote-cache` 上场了,它本质上就是一个转发保存程序,收到请求后,重定向到真正的远程资源,并将资源原样返回的同时将资源保存到本地。 修改 `_CCSettings` 中的 `server` 字段: ```js window._CCSettings = { server: `http://127.0.0.1:9999/${originServer}`, }; ``` 然后再次尝试 `loadCCBundle`,当所有远程 Bundle 都进行 `loadCCBundle`之后,就可以对 `_CCSettings` 中的 `server` 字段做一个小调整,将远程资源改成本地资源: ```js window._CCSettings = { server: `/https.xxx.com/xxxxxxxxxx`, }; ``` 此时游戏已经完成远程资源的本地化了。 某些游戏是运行时通过 JS 动态加载的,此类逻辑没法提前预加载,只能通过人工的方式去到对应的场景下触发下载,做这类逻辑的游戏一般都比较捞。
快游戏
快应用
OPPO 快游戏在浏览器复现运行
如遇到文件无法下载,可右键复制链接打开标签页粘贴下载!
如果您觉得文章或项目对您有帮助,戳我请博主喝一杯咖啡叭!
正在加载验证组件...
取消回复
提交评论
瞅一瞅叭
收一个 Reqable 永久版订阅
最新评论
joey: 我是Mac m3 pro,用dmg安装后点击APP没反应,还需要...
aa: 感谢分享
navicat: Linux x86 下载后也是需要注册了
qq: 兄弟,这arm架构的也得注册了
蓝播电影网: 最近也在研究Telegram相关的自动化工具,这篇文章提到的漏洞...
呃呃呃: 下载之后 用不了啊
fly: 补充一个arm架构的Linux版本https://downloa...
关于站长
广东 佛山
liesauer#liesauer.net
LiesAuer
CC BY-NC-SA 4.0
粤ICP备16094588号-1
萌ICP备20245567号
茶
茶ICP备2025080027号
Theme
Jasmine
by
Kent Liao