v1.10 资源升级指南

本文将详细介绍旧版本 Creator 项目升级到 v1.10 时的注意事项。如果你不是 Creator 旧版本的用户,不需要阅读本文。

在 v1.10 之前的 获取和加载资源 文档中,我们有提到过 Creator 的资源分成了 AssetRawAsset 两种。当时这样划分主要是为了尽量重用已有的 Cocos2d-x 基础模块,并且降低 Cocos2d-x 用户的上手门槛。不过我们仍一直希望把 RawAsset 全部替换成标准的 Asset,随着 Creator 这两年的发展,是时候进行一轮重构了。重构后可以简化编辑器和引擎对资源的处理方式,减小发布后的 settings.js 文件体积,同时提升用户的开发体验。

为了带来平滑的升级体验,我们将在一段时间内保留对 RawAsset 的兼容。从 v1.10 开始,会先支持调整后新的 API,并且对已经废弃的用法提出警告,请用户根据警告和本文的说明对代码进行调整,升级到新的用法。等到 v2.1 以上的某个版本,才会全面移除对 RawAsset 的兼容。

美术策划 而言,项目中的所有资源,例如场景、动画、Prefab 都不需要修改,也不用升级。
程序 而言,影响主要体现在原先在代码中用 URL 字符串表示的资源,需要都改为直接引用加载后的实际资源对象。Creator 中和资源操作有关的 API 也将由传入资源 URL 改为传入资源对象。本文将详细介绍有关内容。

常见问题

我需要手动升级吗?

如果有下列情况,你需要升级:

  • 你在自己的游戏代码中直接声明了这些类型:cc.Texture2D, cc.RawAsset, cc.AudioClipcc.ParticleAsset
  • 你扩展了引擎或编辑器,定义了新的直接继承自 cc.RawAsset 的类型。
  • 你通过 cc.loader.loadRes 加载了 resources 文件夹下的 .json 后缀的文件。

如果有下列情况,可能需要升级:

  • 你在自己的游戏代码中直接调用了 cc.audioEnginecc.textureCache
  • 你使用 cc.loader 加载了远程服务器上的文本、粒子。

我其实并不确定要升级哪些东西?

Cocos Creator 是一个非常重视兼容性的引擎,代码中所有需要升级的部分,都会在编辑器或者游戏运行时给出警告。只要你根据错误信息调整了 API 用法就可以了。

旧项目有对资源管理做一些特殊操作,我不敢乱改,怎么办?

RawAsset 调整为 Asset,本质上无非就是从引擎层面把字符串转变成对象。只要保证跟引擎交互时,所使用的是对象即可,原先项目内部如果想要继续使用字符串也是可以的。你要做的无非就是,从引擎获取对象后先转换为字符串,传字符串给引擎前先转换为对象。

  • Asset 转字符串
    对于 Texture2D, RawAsset, AudioClip 和 ParticleAsset 类型的资源来说,可以直接通过 .nativeUrl 获得原有的 URL。如果无法获取则说明这是其它类型的 Asset 对象,其它类型的对象本来就不用升级,所以不用修改。
    var url = this.file.nativeUrl || this.file;
  • 字符串转 Asset
    cc.loader.loadRes(musicURL, cc.AudioClip, function (err, audioClip) {
        cc.log(typeof audioClip);  // 'object'
    });

升级步骤

  • 重命名旧版本 Cocos Creator 所在目录,然后安装新版本 Cocos Creator。这样新旧两个版本就能共存。
  • 备份好旧版本的工程后,使用新版 Cocos Creator 打开原有工程,Creator 将对有影响的资源重新导入,第一次升级时会稍微多花一点时间,导入完毕后就会打开编辑器主窗口。
  • 工程打开后,可能会出现一堆黄色的警告,警告一般都不会影响游戏的预览发布,但是强烈建议都尽快解决。下面我将对常见的警告信息进行讲解。

"Please change the definition of property 'audio_bgMusic' in class 'FOO'..."

这是一类升级过程中最常见的错误,其中 FOO 是你声明的 CCClass 的类名,也就是文件名,audio_bgMusic 是你的属性名。你需要在 FOO.js 中找到 audio_bgMusic 定义的地方,然后根据后面的提示信息进行修改。后面的提示信息假设为:

"the use of declaring a property in CCClass as a URL has been deprecated..."

这句话的意思是,你在声明 audio_bgMusic 属性的时候,指定了 url 类型,现在已经不支持使用 url 了。通过查找项目中的 FOO.js,你能找到原先类似这样的定义方式:

    // FOO.js

    audio_bgMusic: {
        default: ***,
        url: cc.AudioClip,
    },

将 url 改为 type,并且确保 default 为 null。

    audio_bgMusic: {
        default: null,
        type: cc.AudioClip,  // use 'type:' to define Asset object directly
    },

这样一来,游戏场景加载后,audio_bgMusic 就会是一个 AudioClip 类型的对象,而不是原先的 audio 字符串。为了确保游戏逻辑不会出错,请继续在项目中全局搜索 audio_bgMusic,确保你不会对这个变量做任何字符串相关的 substring、replace 等调用,否则请先通过 audio_bgMusic.nativeUrl 得到真实的 URL。

注意:如果你原先定义的类型是 cc.RawAsset,除了修改 url 为 type,连带类型也应该改为 cc.Asset
假如原来是:

    // 声明时
    manifest: {
        default: ***,
        url: cc.RawAsset
    },

    // 访问时
    this._am = new jsb.AssetsManager(this.manifest, storagePath);

请修改为:

    // 声明时
    manifest: {
        default: null,
        type: cc.Asset
    },

    // 访问时
    this._am = new jsb.AssetsManager(this.manifest.nativeUrl, storagePath);

"properties in CCClass can not be abbreviated if they are of type RawAsset"

除了前面提到的警告信息,你还有可能看这个警告。这句话的意思是,你在声明 audio_bgMusic 属性的时候,使用了将来有可能引起歧义的简便形式,这些简写暂时被废弃了,等到大部分项目都平滑升级上去后,才会重新支持。通过查找项目中的 FOO.js,你能找到原先类似这样的定义方式:

    audio_bgMusic: cc.AudioClip,

你需要参照前面的修改方式,使用 type + default 进行完整声明:

    audio_bgMusic: {
        default: null,
        type: cc.AudioClip,
    },

这样一来,游戏场景加载后,audio_bgMusic 就会是一个 AudioClip 类型的对象,而不是原先的 audio 字符串。相关的注意事项都和前面一致,这里不再赘述。

"textureCache.addImage(url) - The type of the url should be string, not Texture2D..."

这个警告一般是如下代码引起的:

    // 按照上面的文档升级后的写法
    tex: {
        default: null,
        type: cc.Texture2D,
    },

    // 原先获取 texture 的代码
    var texture = cc.textureCache.addImage(this.tex);

这个警告的意思是,当你调用 addImage 时,你传入的已经是一个 Texture2D 对象了,所以直接使用这个对象就行,不需要再做加载。因为升级后的 tex 就已经是一个 Texture2D 了。也就是说你只要:

    var texture = this.tex;

"Since 1.10, cc.audioEngine.play accept cc.AudioClip instance directly, not a URL string..."

这个警告一般是这种代码引起的:

    var url = cc.url.raw('resources/bg.mp3');
    cc.audioEngine.play(url);

请改成:

    cc.loader.loadRes('bg', cc.AudioClip, function (err, clip) {
        cc.audioEngine.play(clip);
    });

Protobuf 相关更新

如果你之前适配了 protobuf,升级到 1.10 后加载 proto 文件时可能会遇到麻烦,只需要做如下调整即可。下面示范的代码可能和你正使用的 protobuf 不太一样,不过原理是相同的。

假设原先使用这样的代码加载 proto:

ProtoBuf.loadProtoFile(cc.url.raw('resources/data.proto'), ...);

由于 路径经过 cc.url.raw 的转化后,将无法再用于相对路径的解析,因此 protobuf 内部加载关联的文件时可能会失败。请改成直接用:

ProtoBuf.loadProtoFile('data.proto', ...);

然后请修改 loadProtoFile 的实现,将原先使用 cc.loader.load 等方法进行加载的代码调整为:

ProtoBuf.loadProtoFile = function (filename, callback, builder) {
    ...
    cc.loader.loadRes(filename, function (error, res) {
        ...
        ProtoBuf.loadProto(res.text, builder, filename);
    });
});

其它更新

新增了 cc.TextAsset 用于加载文本文件

从 1.10 开始,常见的文本格式,如 .txt, .plist, .xml, .json, .yaml, .ini, .csv, .md,都会导入为 cc.TextAsset。可以这样访问 TextAsset:

    // 声明
    file: {
        default: null,
        type: cc.TextAsset,
    },

    // 读取
    var text = this.file.text;

新增了 cc.JsonAsset 用于加载 JSON 文件

从 1.10 开始,项目 assets 文件夹下的所有 .json 文件(不含发布后的 imports 目录),都会导入为 cc.JsonAsset。你必须调整 loader 相关代码,否则运行时会报错,例如原先是:

    cc.loader.loadRes('configs/npc', function (err, json) {
        loadNpc(json);
    });

需要改成:

    cc.loader.loadRes('configs/npc', function (err, asset) {
        loadNpc(asset.json);
    });

此外,还可以直接读取:

    // 声明
    npcList: {
        default: null,
        type: cc.JsonAsset,
    },

    // 读取
    var json = this.npcList.json;
    loadNpc(json);

其余未知类型默认也全都导入为 cc.Asset

对从编辑器导入的未知类型的文件来说,原先都是导入为无类型的 cc.RawAsset,现在会导入为 cc.Asset。声明方法和上面一样,将 url: cc.RawAsset 改为 type: cc.Asset,访问时也同样采用 asset.nativeUrl 这样的方式获得原始 url 即可。

如果需要对构建后的图片重新进行压缩

从 v1.10 开始,构建后的图片会以 uuid 进行命名,这样会导致你无法从文件名直接判断出图片原先在项目中的位置。v1.10 处理起来会比较麻烦,建议直接升级到 v2.0,然后需要对构建流程做一些定制,请参考范例(GitHub | Gitee)。

条与 "" 相匹配的结果

    没有与 "" 匹配的结果