Load流程是整个资源加载管线的最后一棒,由Loader这个pipe负责(loader.js)。通过Download流程拿到内容之后,需要对内容做一些“加载”处理。使得这些内容可以在游戏中使用。这里并不是所有的资源都需要进行一个加载处理,目前只有图片、Json、Plist、Uuid(Prefab、场景)等资源才会执行加载的流程,其他的资源在Download流程之后就可以在游戏中使用了。
Loader处理
Loader的handle接收一个item和callback,根据item的type在this.extMap中获取对应的loadFunc。
Loader.prototype.addHandlers = function (extMap) {
this.extMap = JS.mixin(this.extMap, extMap);
};
Loader.prototype.handle = function (item, callback) {
var loadFunc = this.extMap[item.type] || this.extMap['default'];
return loadFunc.call(this, item, callback);
};
资源的加载方式
Loader的this.extMap记录了各种资源类型的下载方式,所有的类型最终都对应这5个加载方法,loadNothing、loadJSON、loadImage、loadPlist、loadUuid,它们对应实现了各种类型资源的加载,通过Loader.addHandlers可以添加或修改任意资源的加载方式。加载结束后将可用的内容返回。
// 无需加载,即经过前面的下载已经可用了,例如font、script等资源
function loadNothing (item, callback) {
return null;
}
// 使用JSON.parse进行解析并返回
function loadJSON (item, callback) {
if (typeof item.content !== 'string') {
return new Error('JSON Loader: Input item doesn\'t contain string content');
}
try {
var result = JSON.parse(item.content);
return result;
}
catch (e) {
return new Error('JSON Loader: Parse json [' + item.id + '] failed : ' + e);
}
}
// 创建Texture2D,并根据图片的内容初始化Texture2D,最后添加到cc.textureCache中
function loadImage (item, callback) {
if (sys.platform !== sys.WECHAT_GAME && !(item.content instanceof Image)) {
return new Error('Image Loader: Input item doesn\'t contain Image content');
}
var rawUrl = item.rawUrl;
var tex = cc.textureCache.getTextureForKey(rawUrl) || new Texture2D();
tex.url = rawUrl;
tex.initWithElement(item.content);
tex.handleLoadedTexture();
cc.textureCache.cacheImage(rawUrl, tex);
return tex;
}
// 使用cc.plistParser进行解析并返回
function loadPlist (item, callback) {
if (typeof item.content !== 'string') {
return new Error('Plist Loader: Input item doesn\'t contain string content');
}
var result = cc.plistParser.parse(item.content);
if (result) {
return result;
}
else {
return new Error('Plist Loader: Parse [' + item.id + '] failed');
}
}
loadUuid
loadUuid用于加载creator内部统一规划的资源,每个uuid都会对应一个json对象,可能是prefab、spriteFrame,等等。在loadUuid这个方法中,最关键的操作就是cc.deserialize反序列化把资源对象创建了出来,其次就是加载依赖资源。
uuid的解析首先需要一个json对象,如果item的content是string类型,则进行解析,如果是object类型,则直接使用item.content,如果既不是string也不是object则直接报错。
function loadUuid (item, callback) {
if (CC_EDITOR) {
MissingClass = MissingClass || Editor.require('app://editor/page/scene-utils/missing-class-reporter').MissingClass;
}
// 获取json对象,如果是string则进行解析,如果是object则直接使用,报错则返回Error对象
var json;
if (typeof item.content === 'string') {
try {
json = JSON.parse(item.content);
} catch (e) {
return new Error('Uuid Loader: Parse asset [' + item.id + '] failed : ' + e.stack);
}
} else if (typeof item.content === 'object') {
json = item.content;
} else {
return new Error('JSON Loader: Input item doesn\'t contain string content');
}
// 根据是否场景对象、编辑器环境来决定classFinder的实现。
var classFinder;
var isScene = isSceneObj(json);
if (isScene) {
if (CC_EDITOR) {
// 编辑器 + 场景的模式下,使用MissingClass.classFinder作为包裹函数
MissingClass.hasMissingClass = false;
classFinder = function (type, data, owner, propName) {
var res = MissingClass.classFinder(type, data, owner, propName);
if (res) {
return res;
}
return cc._MissingScript.getMissingWrapper(type, data);
};
classFinde