cocos-creator使用记录32_动态加载


1.前言
1.1.可动态加载的资源
(1)Asset
cc.SpriteFrame,cc.AnimationClip,cc.Prefab
Asset 的加载是统一并且自动化的,相互依赖的 Asset 能够被自动预加载。
例如,当引擎在加载场景时,会先自动加载场景关联到的资源,这些资源如果再关联其它资
源,其它也会被先被加载,等加载全部完成后,场景加载才会结束。
因此只要你拿到了一个 Asset 对象,这个对象一定是已经加载结束的,可以直接通过对象上
的属性访问到资源的所有数据。

(2)Raw Asset
为了兼容 Cocos2d 的一些既有 API,我们把保留原始资源文件扩展名资源叫做 "Raw Asset"。
cc.Texture2D,cc.AudioClip,cc.ParticleAsset
Raw Asset 在脚本里由一个 url 字符串来表示,当你要在引擎中使用 Raw Asset,只要把 
url 传给引擎的 API,引擎内部会自动加载这个 url 对应的资源。

1.2.可动态加载的资源所在的文件夹
(1)所有需要通过脚本动态加载的资源,都必须放置在 resources 文件夹或它的子文件夹下。
resources 需要在 assets 文件夹中手工创建,并且必须位于 assets 的根目录。

(2)resources 文件夹里面的资源,可以关联依赖到文件夹外部的其它资源,同样也可以被外部
场景或资源引用到。项目构建时,除了已在 构建发布 面板勾选的场景外,resources 文件夹里面
的所有资源,连同它们关联依赖的 resources 文件夹外部的资源,都会被导出。
所以如果一份资源不需要由脚本直接动态加载,那么不用放在 resources 文件夹里。

1.3.动态加载Asset
Creator 提供了 cc.loader.loadRes 这个 API 来专门加载那些位于 resources 目录下的 
Asset。loadRes 一次只能加载单个 Asset。调用时,你只要传入相对 resources 
的路径即可,并且路径的结尾处不能包含文件扩展名。
// 加载 Prefab
cc.loader.loadRes("test assets/prefab", function (err, prefab) {
    if(err){
        console.log("未找到预制文件");
        return;
    }
    var newNode = cc.instantiate(prefab);
    cc.director.getScene().addChild(newNode);
});

// 加载 AnimationClip
cc.loader.loadRes("test assets/anim", function (err, clip) {
    myNode.getComponent(cc.Animation).addClip(clip, "anim");
});

// 加载 SpriteAtlas(图集),并且获取其中的一个 SpriteFrame
// 注意 atlas 资源文件(plist)通常会和一个同名的图片文件(png)放在一个目录下, 所以
需要在第二个参数指定资源类型
cc.loader.loadRes("test assets/sheep", cc.SpriteAtlas, function (err, atlas) {
    var frame = atlas.getSpriteFrame('sheep_down_0');
    sprite.spriteFrame = frame;
});

1.4.动态加载的Asset资源的释放
loadRes 加载进来的单个资源如果需要释放,可以调用 cc.loader.releaseRes,
releaseRes 只能传入一个和 loadRes 相同的路径,不支持类型参数。
cc.loader.releaseRes("test assets/anim");
此外,你也可以使用 cc.loader.releaseAsset 来释放一个具体的 Asset 实例。
cc.loader.releaseAsset(spriteFrame);

1.5.动态加载 Raw Asset
Raw Asset 可以直接使用 url 从远程服务器上加载,也可以从项目中动态加载。
对远程加载而言,原先 Cocos2d 的加载方式不变,使用 cc.loader.load 即可。
对项目里的 Raw Asset,加载方式和 Asset 一样:
// 加载 Texture,不需要后缀名
cc.loader.loadRes("test assets/image", function (err, texture) {
    ...
});

Raw Asset 加载成功后,如果需要传给一些 url 形式的 API,还是需要给出完整
路径才行。你需要用 cc.url.raw 进行一次 url 的转换:
// 原 url 会报错!文件找不到
var texture = cc.textureCache.addImage("resources/test assets/image.png");

// 用 cc.url.raw,此时需要声明 resources 目录和文件后缀名
var realUrl = cc.url.raw("resources/test assets/image.png");
var texture = cc.textureCache.addImage(realUrl);

1.6.资源批量加载
cc.loader.loadResAll 可以加载相同路径下的多个资源:
// 加载 test assets 目录下所有资源
cc.loader.loadResAll("test assets", function (err, assets) {
    // ...
});

// 加载 sheep.plist 图集中的所有 SpriteFrame
cc.loader.loadResAll("test assets/sheep", cc.SpriteFrame, function (err, assets) {
    // assets 是一个 SpriteFrame 数组,已经包含了图集中的所有 SpriteFrame。
    // 而 loadRes('test assets/sheep', cc.SpriteAtlas, function (err, atlas) {...}) 
    // 获得的则是整个 SpriteAtlas 对象。
});

2.实际使用中
loadLevel: function(){ //加载关卡
    var self = this;
    self.levelNode.removeAllChildren();
    var levelNum = common.setLevelMap(common.currentLevel - 1);
    cc.loader.loadRes("zqddn_zhb/prefab/level/zqddn_zhb_level" + levelNum, function (err, prefab) {
        if(err){
            console.log("未找到关卡预制文件");
            self.showTipsUI("网络已断开,请检测网络连接");
            return;
        }
        var level = cc.instantiate(prefab);
        if(level && self.levelNode){
            self.levelNode.addChild(level);
        }
    });
},

总结:
(1)动态加载会有明显的短暂延迟,可优化的地方就在图集上了,尽量将每个关卡要使用的资源放
在一起,且图集大小要控制在一定范围内,比如一张图包含10关的资源,压缩后,图片大小在
200k左右。每个关卡的公共资源,要独立出来,用一张图集保存。
(2)把res资源放到后台后,资源不是在微信打开游戏时全部下载到本地的,而是
按要显示的场景需要使用哪些资源,就先下载哪些资源。于是动态加载关卡时,若手机断网,
就会下载不了关卡的对应资源,关卡也就显示不了了。

猜你喜欢

转载自blog.csdn.net/haibo19981/article/details/81251848