CocosCreator 2.4.3热更新实现方案(AssetBundle),大厅+子游戏模式快速实现

实现功能

  1. 实现 大厅+子游戏 模式,
    低优先级模块可引用高优先级模块中资源及脚本
    可配置模块依赖,被依赖的模块会自动更新
  2. 多模块在同一工程下开发.
  3. 热更新模块可以打到包里随发布包一起发布,免去首次启动游戏就完整下载模块
  4. 支持AutoAtlas自动图集预加载.

示例工程:
https://github.com/sss0vvv/CocosCreatorHotUpdate.git

项目环境

macOS Big Sur 11.1
Cocos creator 2.4.3 
Xcode 12.3
Android Studio 4.1
NodeJs 
XAMPP

关于 Asset Bundle

以下 Asset Bundle 简称 AB.
调用cc.assetManager.loadBundle加载AB时可传入参数version指定某个版本,如果该版本已经存在于可读写路径下的gamecaches则从本地加载,否则先从远程服务器下载到本地再加载.

gamecaches/cacheList.json 记录了本地缓存的文件.

{
    "files": {
 "http://192.168.69.197:8089/dashboard/hotTest/remote/ABLobby/index.808a1.js": {
            "bundle": "ABLobby", 
            "url": "ABLobby/11111610276469253.js", 
            "lastTime": 1616276601323
        }, 
    }, 
    "version": "1.1"
}

Asset Bundle官方指引
https://docs.cocos.com/creator/manual/zh/asset-manager/bundle.html

实现过程

工程结构

新增一个大厅模块、两个子游戏模块, 均设置为asset bundle , 配置为远程包 . 如果存在AB引用另一个AB的情况, 被引用的AB 设置更高优先级. 示例中 ABSubgame2 引用了 ABSubGame1 和 ABLobby 中的文件和代码.
在这里插入图片描述

快速使用代码

let moduleMagObj    = cc.instantiate(this.ModuleMagPreFab)
moduleMagObj.parent = this.node  
window._G_moduleMag = moduleMagObj.getComponent("ModuleManager")  
_G_moduleMag.initCom({
    useHotUpdate : true ,     // 是否启用热更新 
}) 
//-------------------
// 复制包内模块到可读写路径下,避免首次加载模块时从远程完整拉取
_G_moduleMag.execUnpackage(()=>{
    _G_moduleMag.reqVersionInfo(()=>{  // 获取最新版本
        let loadAb = ["ABLobby"]
        // loadAb = ["ABLobby", "ABSubGame1", "ABSubGame2"]
        _G_moduleMag.hotUpdateMultiModule(loadAb,()=>{ // 更新模块到最新版本
            _G_moduleMag.addModule("ABLobby", (moduleObj)=>{ // 加载模块
                let abObj = moduleObj.getABObj()
                abObj.load('root/Scene/LobbyRoot', cc.Prefab, (err, prefab)=>{  // 使用模块资源 
    				//...
                }) 
            })
        })
    })
})
// 定时检测更新
// _G_moduleMag.reqLoopVersionInfo()

构建发布

Creator 构建

MD5 Cache 打钩.
在这里插入图片描述

制作热更新资源

执行构造HotRes_macos.sh, 构建出来的remote将被拷贝到hotRes目录下, 同时verconfig.json中的版本号也将被更新.
hotRes目录下文件上传到下载服务器,注意服务器上保留remote这级目录, 我配置的下载地址"http://192.168.69.197:8089/dashboard/hotTest/" .
在这里插入图片描述

制作随包发布模块

执行构造PKgamecaches_macos.sh, 构建出来的remote将被拷贝到assets/PKgamecaches目录下, 指定的模块将会打到发布包里.
在这里插入图片描述

测试功能

分别测试模块随包发布模块完整下载
示例使用Xcode模拟器, 如果跑模拟器时遇到找不到文件的日志, 将main.js 和 src 从Xcode移除引用再从文件夹拖进来.

在这里插入图片描述

模块完整下载

将可读写路径下文件清除、将 PKgamecaches 删除, 启动模拟器搜索**[HotUIHelper]**日志查看更新进程.

这是我这里的,实际路径要跑起来看日志.
JS: [HelloWorld] jsb_writable_: /Users/svsv/Library/Developer/CoreSimulator/Devices/8863F5D0-DDE1-472A-8655-4A8E46EF0F37/data/Containers/Data/Application/126C4155-5508-430B-9439-34B7261643C3/Documents/
在这里插入图片描述

windows下测试

将 /build/jsb-link/assets/ 下的src, assets, main.js三个文件覆盖到win32Example_exe文件夹, 执行 hot_example.exe启动游戏, 单击键盘TAB键保存Log日志到可读写路径下 alogRecord.txt .
在这里插入图片描述

项目文件解释

ModuleMagPreFab.prefab 用于挂载热更新代码.
assets/Script/ModuleMag/ 包含了热更新涉及的代码.

  1. ModuleCom.js :
    一些常用的方法

  2. ModuleConst.js :
    一些参数定义

  3. HotUIHelper.js :
    展示更新过程中的提示信息

  4. Module.js :
    模块类,
    4.1负责加载AB实例

let abUrl = "http://192.168.69.197:8089/dashboard/hotTest/"+abName
cc.assetManager.loadBundle(abUrl,  {version:"1.1.1"}, (err, bundle)=> {
	//这里仅仅下载到AB构建出来的 index.e350c.js 和 config.e350c.json
})

4.2 下载对应AB版本的资源.使用preloadDir下载根目录root下的文件

bundle.preloadDir("root", (finish, total, item)=>{
	
}, (error, items)=>{

})

4.3 打开AB配置文件 config.e350c.json 可以看到, 项目中使用到的AutoAtlas构建出的png文件并没有配置到里面.
所以preloadDir是不会去下载AutoAtlas图集文件的.
通过 bundle._config.assetInfos._map 可以看到自动图集的项是没有path字段的,把这些项筛选出来用cc.assetManager.preloadAny下载.

cc.assetManager.preloadAny(autoAtlas, { __requestType__: 'url', type: null, bundle: this._abObj.name }, 
    (finish, total, item)=>{
    }, (error, items)=>{
    }   
);
  1. ModuleManager.js :
    模块管理类, 负责构建 Module , 以及 Module 新版本检测.
    游戏启动后从远程请求版本配置文件verconfig.json, 对比本地的版本信息, 发现新版本则交给 Module 下载更新, 更新完成后替换本地版本号.

  2. UnpackageHelper.js :
    6.1 负责将随包发布的AB复制到可读写路径下gamecaches .
    6.2 为了避免新安装的客户端cc.assetManager.loadBundle加载远程AB时,在可读写路径下gamecaches找不到该版本而从服务器完整下载AB, 所以将随包AB复制到可读写路径下, 以达到加载AB逻辑一致的目的.

  3. verconfig.json :
    版本控制配置文件.
    设置AB版本号、优先级和依赖关系.

{
    "clientMin": "1.0.0", 
    "modules": {
        "ABLobby": {
            "resVersion": "808a1", 
            "showVer": "1.0.127", 
            "priority": 6, 
            "depend": [ ]
        }, 
        "ABSubGame1": {
            "resVersion": "e350c", 
            "showVer": "1.0.127", 
            "priority": 5, 
            "depend": [
                "ABLobby"
            ]
        }, 
        "ABSubGame2": {
            "resVersion": "3de91", 
            "showVer": "1.0.127", 
            "priority": 4, 
            "depend": [
                "ABSubGame1"
            ]
        }
    }
}

模块随包发布

保留 PKgamecaches , 启动模拟器搜索**[HotUIHelper]**日志查看更新进程.

注意事项

每个模块中的资源需放在 root 文件夹下

需要跑热更新时,初始化 ModuleManager 传入 useHotUpdate(true) .
请不要用Creator自带模拟器(资源结构不同)跑热更新,可以使用Xcode模拟器或者安卓真机调试热更新.

修改 makePKgamecaches.js 中的 hotUrl 为你的资源下载地址. 修改 ModuleConst.js 中的 hotUrl 为你的资源下载地址.

hotRes上传到资源下载服务器,需保留remote这级目录.

缺陷

1. 热更新模块本身并不支持热更新,功能稳定后这个需求并不是很强烈,如需支持创建一个 Asset Bundle, 把热更模块移过去也可以实现. 
3. 已加载的模块在进行热更新后需要重新进入游戏 cc.game.restart() , 未加载的模块热更后则不需要重启.
4. 没有统计热更新文件大小.
  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
以下是一个简单的shader效果示例: ``` CCEffect %{ techniques: - name: hit-effect passes: - vert: shader.vert frag: shader.frag blendState: targets: - blend: true blendSrc: src_alpha blendDst: one_minus_src_alpha properties: hitColor: { value: [1.0, 0.0, 0.0, 1.0], type: color } }% CCProgram hit-effect { CCVertexShader shader.vert %{ precision highp float; attribute vec2 a_position; attribute vec2 a_uv0; varying vec2 uv0; void main () { gl_Position = vec4(a_position, 0, 1); uv0 = a_uv0; } %} CCFragmentShader shader.frag %{ precision highp float; varying vec2 uv0; uniform sampler2D texture; uniform vec4 hitColor; uniform float time; void main () { vec4 color = texture2D(texture, uv0); if (time >= 0.0 && time <= 3.0) { color = mix(color, hitColor, time / 3.0); } else if (time >= 4.0 && time <= 10.0) { color = mix(hitColor, color, (time - 4.0) / 6.0); } gl_FragColor = color; } %} } ``` 将以上代码保存为一个 `.effect` 文件,然后在 `skeleton` 组件上添加一个 `Mesh Renderer` 组件,并将创建的 `.effect` 文件拖放到 `Material` 属性上。在代码中,可以通过设置 `time` 属性的值来控制受击时的颜色变化。例如: ``` let renderer = this.node.getComponent(sp.Skeleton).getComponentInChildren(cc.MeshRenderer); let material = renderer.getMaterial(0); material.setProperty('time', 0); material.setProperty('hitColor', cc.color(255, 0, 0, 255)); // 受击动作 for (let i = 0; i < 10; i++) { material.setProperty('time', i); } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值